- Status: proposed
- Date: 2026-02-15
Recent runtime behavior exposed a philosophical and architectural mismatch:
- A Tool returned
Outcome.okwith self-signaled weak status (for examplesuccess_no_parse+ empty list). - Runtime coercion converted that success into
Outcome.error(low_utility)at boundary validation. - Calls became safer, but Tool behavior did not evolve: runtime compensated silently.
This conflicts with project tenets:
- Agent-first mental model: Tool Builders and Tools should learn through explicit feedback loops.
- Runtime ergonomics and clarity: runtime should enforce boundaries, not rewrite domain semantics.
- Tolerant interfaces by default: runtime can normalize shape/key tolerance, but must not silently reinterpret success intent.
- Ubiquitous language: Tool Builder forges contracts; Tools either succeed meaningfully or fail honestly.
Related decisions:
- ADR 0014 enforces delegated
deliverableshape at outcome boundaries. - ADR 0015 introduces
low_utilityandwrong_tool_boundaryas typed referral/usefulness outcomes. - ADR 0012 provides persisted repair/regeneration once failures are explicit.
Runtime semantics remain observational for utility quality; utility pressure must come from explicit contracts and telemetry, not status rewriting.
Runtime MUST NOT convert Outcome.ok into Outcome.error purely from heuristic status/message inspection.
Allowed runtime transformations:
- tolerant shape/key canonicalization (ADR 0014),
- contract-shape violation mapping to typed
contract_violation, - serialization/transport normalization.
Disallowed:
- semantic reinterpretation of Tool-authored success into failure based on ad hoc status strings.
Utility requirements that should fail inline must be represented in enforceable contract fields under deliverable constraints (not only free-form acceptance prose).
Examples of enforceable utility constraints (v1 direction):
- array
min_items, - object field non-empty constraints,
- bounded required collection constraints on declared keys.
If constraint fails, runtime returns typed contract_violation through existing boundary mechanism.
Tools should be nudged to emit:
Outcome.error(error_type: "low_utility", ...)when output is structurally valid but not useful,Outcome.error(error_type: "wrong_tool_boundary", ...)when task crosses capability boundaries.
These remain Tool-authored semantics, not runtime-authored rewrites.
When Tools repeatedly return weak-but-OK outputs:
- preserve emitted outcome status,
- record weak-success telemetry and user-correction signals,
- apply evolution pressure in out-of-band maintenance/evaluation loops.
This preserves emergence while still driving improvement.
Inline reliability stays deterministic via:
- boundary validation,
- fresh execution repair retries,
- persisted artifact repair.
Emergence stays intact because semantic ownership remains with Tool output + contract evolution.
In scope:
- policy that runtime must not coerce utility semantics from success to error;
- contract-driven approach for inline utility failures;
- telemetry-driven approach for non-inline utility drift;
- prompt guidance updates that prioritize Tool-authored typed outcomes.
Out of scope:
- runtime-autonomous tool decomposition/splitting;
- domain-specific heuristics for websites/sources;
- replacing delegated boundary validation from ADR 0014.
- Tool behavior remains legible and accountable (no hidden semantic rewrite layer).
- Repair/regeneration pressure flows through explicit typed failures.
- Tool Builders are incentivized to forge stronger machine-checkable contracts.
- Runtime remains a boundary enforcer and observer, not a compensating policy engine.
- Some weak successes may reach users until contracts or tools evolve.
- Contract schema must evolve to express quality constraints without overfitting.
- Out-of-band evaluation quality depends on telemetry signal quality.
- Keep runtime heuristic coercion (
ok->low_utility)- Rejected: hides semantics from Tool, weakens emergent adaptation.
- Enforce free-form
acceptancetext as executable policy- Rejected: ambiguous, non-deterministic, high risk of brittle parsing.
- Out-of-band only (no inline contract utility constraints)
- Rejected: too slow for high-frequency quality failures that should fail fast.
- Remove success-status heuristic coercion in boundary validator.
- Keep current tolerant shape canonicalization intact.
- Add regression tests to ensure runtime does not rewrite Tool-authored success semantics.
- Extend
deliverablevalidator with minimal machine-checkable utility constraints (v1). - Map violations to
contract_violationwith precise metadata (mismatch, expected vs actual). - Add acceptance tests using movie-style empty-result scenarios.
- Update Tool Builder prompt guidance to encode quality expectations in enforceable
deliverableconstraints. - Keep
acceptanceas explanatory intent, not primary runtime enforcement.
- Record weak-success telemetry +
user_correctionsignals. - Feed these into tool-health/cohesion views and evolution recommendations.
- Prioritize Tool Builder re-forge/decomposition decisions from telemetry evidence.
- Runtime may canonicalize shape; runtime may not rewrite outcome intent.
- Inline failures must be deterministic and machine-checkable.
- Contract evolution must remain Tool Builder-driven.
- Telemetry informs evolution; telemetry must not silently mutate semantics.
- Which minimal
deliverableutility constraints provide highest leverage in v1 (min_items, non-empty keys, both)? - Should repeated weak-success + user-correction signals auto-increase regeneration priority, or only surface recommendations?
- How should utility constraints balance strictness (fast failure) vs tolerance (open-world variability)?