Delegation Contracts for AI Agent Teams: Scope, Acceptance and Failure Handling
Why agent job titles don't prevent broken handoffs, and how a delegation contract with enforced policy, independent acceptance and failure rules can be tested.
This article is published in English.
Picture a product change handled by three agents: add cursor pagination to an API, to the client that calls it, and to the tests. All three report success, yet the client can't parse what the API returns. The API agent emits next_cursor, the client agent expects nextCursor, and the test agent checks mocks that were built around the client's assumption. Every local task looks done, and the combined change breaks on its first real request.
Labeling the agents Engineer, Client Specialist and Reviewer doesn't say which interface wins or who signs off on the result. Those decisions belong in a delegation contract, meaning a concrete assignment that names the inputs, the permitted scope, the required output, the acceptance conditions and what happens on failure. Its worth comes from how the system uses the agreement, and not from producing one more document.
Think of it in layers: a role shapes how an agent approaches the work, while a contract spells out which contributions are admissible. Runtime policy decides what the agent is really able to do, and acceptance decides whether the contribution turns into product state.
Specialization leaves the handoff open
A role describes a viewpoint, such as hunting for security problems, building the client or challenging the design. A task contract describes one particular assignment: use this interface revision, change these files, bring back this evidence. Runtime authority governs what the worker can truly read, modify or run.
Keeping these apart lets a useful role stay useful without making it responsible for everything. A reviewer can spot a breaking change without being allowed to approve it, and an engineer can propose a revised interface without the power to make it the accepted one.
Anthropic's multiagent research from August 2026 makes the dependency problem tangible. In its game-building experiments, prescriptive roles and a CEO-style hierarchy changed little, and the games stayed poor even while some models scored better on coordination measures. The same report notes correlated behavior and correlated mistakes. Those results come from specific experiments and say nothing final about every agent team, and its vulnerability-search comparisons differ in scope and resource use, so raw output totals can't isolate what coordination contributed.
A counterexample exists. Anthropic's engineering write-up of its research system reports gains from parallel research and describes assignments that carry objectives, output formats, tool guidance and boundaries. It also reports higher resource use and warns about work with many dependencies. That argues for taking decomposition seriously, but it doesn't show that a research architecture carries over unchanged to engineering in a shared codebase.
The proposal here concerns the line between delegated work and accepted work. Whether drawing that line explicitly pays for its overhead is something to test.
Write the assignment around the dependency
For the pagination change, begin with the product owner fixing the intended behavior and the API owner approving the interface. Say the interface uses next_cursor, with null marking the final page. API and client workers can then build against one revision while acceptance tests exercise the merged result.
The following YAML is an illustration of a contract for the client worker. Its paths, revision names and check identifiers belong to the example, and it is neither a standard nor part of any framework API.
task_id: pagination-client-17
objective: Fetch successive pages using next_cursor; stop at null.
inputs:
repository:
ref: product-repo
revision: base-42
requirement:
ref: pagination-behavior
revision: r3
interface:
ref: api/pagination.yaml
revision: r7
scope:
writable:
- client/pagination.ts
- tests/client/pagination.test.ts
non_goals:
- interface_changes
- api_changes
- deployment
deliverable:
- patch_against_base-42
- check_results_bound_to_patch_and_input_revisions
acceptance:
checks:
- client-pagination-unit
- pagination-api-client-e2e
owner: product-maintainer
policy_ref: client-worker-v2
failure:
stale_or_conflicting_input: stop_and_report_to_owner
missing_evidence: return_incomplete
authority_required: request_owner_decision
max_attempts: 2
exhausted: return_unaccepted_to_owner
The check names must resolve to real commands and assertions in a registry that the runner controls. In this example they stand for unit checks on cursor handling and an end-to-end check that walks through several pages against the actual candidate API, including the closing null. The client worker may run its own unit checks, while the integration runner generates the combined evidence once both patches exist.
Likewise, policy_ref merely names a policy. The dispatcher has to bind the approved assignment to an authenticated worker and look the policy up in configuration the worker can't edit. An unknown reference, or a request for a stronger policy, must fail validation, and editing the YAML should never hand out extra access.
Limiting the work to two attempts is a local choice that keeps repair loops bounded, and it says nothing about reliability. A finite execution budget set by the owner ensures that no single attempt runs forever.
A structured task is not an authorization boundary. YAML can describe the scope that was intended, and the runtime still has to enforce it.
A path of steps that makes the contract real
Around the workers sits a path of steps. The harness here is simply the software that launches workers, mediates their tools and records what happened.
- Approve the dependencies: product and API owners sign off on the requirement and the interface.
- Validate the assignment: its author provides the contract and the resolved revisions.
- Dispatch under enforced policy: the dispatcher launches isolated API and client workers.
- Produce proposals: workers return proposed patches and not accepted changes.
- Integrate and check: the integration runner builds the combined candidate and gathers evidence from the checks.
- Decide on acceptance: the acceptance owner rejects, asks for bounded repair or accepts.
- Commit via the guarded path: an authorized integrator commits the accepted candidate into accepted state.
The assignment can be authored by a human or by another agent. Two checks follow. A deterministic validator confirms the structure and that every reference resolves, and the responsible owner confirms the text really captures the product requirement. After that the dispatcher holds back until approved dependencies exist, loads the pinned inputs and launches each worker within its boundary.
Four questions need to stay separate. Schema validity asks whether the required fields exist and are well formed. Semantic adequacy asks whether the assignment describes the right work. Permission enforcement asks whether a worker can exceed its authority. Outcome evidence asks whether the combined product satisfies the requirement. A document that is structurally valid answers only the first.
For enforcement, a list of writable paths has to become a genuine runtime restriction, backed by a changed-file check at integration. Shell access mustn't offer a second way around file or network controls. A separate checkout keeps proposals apart, yet it isn't an authorization boundary on its own.
GitHub's managed-permissions announcement of September 9 describes operations that are blocked centrally, require approval or are permitted, with limits that workspace settings can't weaken. Its architecture write-up on Agentic Workflows describes isolated execution and staged, vetted writes. Both are examples of enforcement mechanisms, and neither proves that this delegation design improves delivery or guarantees correct changes.
Ownership of the merged outcome
Back in the pagination example, the integration runner merges the API and client proposals in a throwaway candidate workspace. It checks scope, verifies the input revisions and runs the registered acceptance checks against exactly that candidate. The acceptance owner then reads the evidence and weighs any product judgment the checks can't settle.
Independent acceptance means the worker that did the job doesn't alone control the criteria and the evidence. End-to-end assertions and fixtures stay out of worker write access, and results are tied to the candidate digest. Acceptance may combine deterministic checks with a human maintainer, and another LLM is optional. Naming a model Supervisor doesn't establish authority or make its judgment trustworthy.
Only an authorized owner may change the acceptance criteria, and does so with a recorded reason and a fresh assignment revision. The executing agent can ask for a change, but it must not slip a failing test out of the suite or redefine pagination as finished after one page.
Finally an authorized integrator commits the accepted candidate by way of the guarded merge path already in place. The acceptance record names the exact candidate and the input revisions it covers. Should the target branch advance before integration, the candidate is rebuilt and rechecked against the new base first.
Outputs that conflict return to whoever owns the disputed boundary. Two plausible interfaces are still two incompatible interfaces, so until that owner chooses, neither proposal becomes the shared definition just by arriving first.
Failure handling belongs in the same workflow
Each of these cases should be tried against the pagination workflow in isolation, with an expected response and a place responsible for enforcing it.
When both workers try to change the interface, the dispatcher rejects overlapping ownership of it and runtime restrictions deny the unauthorized edit. Integration rejects any patch that strays outside its assigned scope, and the API owner decides on the requested change.
If the interface revision shifts while work is under way, the dependency check flags the proposal as stale. The owner chooses whether to reissue it against the new revision, and integration may not quietly accept evidence collected for the old one.
When plausible code turns up without evidence, the acceptance gate records it as incomplete. A trusted runner executes the required checks, and a confident completion message can't stand in for results.
When a worker stops halfway, the harness records the interruption and keeps the partial proposal on its own. Before replacement work starts, the old attempt is retired so it can't later submit an accepted result.
If a retry might create the same preview environment twice, the external-action adapter first reconciles the earlier request. Where the provider supports deduplication a stable operation key is used, and effects that remain uncertain go to the owner for review.
If integration needs authority the worker doesn't hold, tool policy blocks the operation and sends a request to the right owner. The proposal stays unaccepted until that decision arrives.
The preview-environment scenario is an optional add-on to the example, owned by the integration service, with deployment kept outside the client worker's remit. One operation key names a single intended effect across all retries, an attempt identifier separates individual executions, and a retry must not mint a new operation just to get past an ambiguous response.
Temporal's early Agent Harness account describes durable execution and control points around an inner agent loop, with recovery and approval waits. It's an evolving vendor project and not independent comparative evidence. Provider-specific deduplication or reconciliation is still needed for external actions, since durable orchestration alone doesn't demonstrate exactly-once effects in an arbitrary service, and Temporal's own retry documentation calls for downstream duplicate detection when retrying.
Each repair spends from the declared attempt and resource budget. When either is exhausted the workflow hands back an unaccepted result along with its evidence and a named owner. Escalations also need an expiry or a way to cancel, so responsibility doesn't end up lost inside an abandoned conversation.
Contracts can formalize the wrong work
Overhead is the strongest objection. When a single agent edits an isolated function, an issue plus the existing tests may already give enough scope and acceptance control. Disposable prototypes and independent low-risk research tasks may need hardly more than clear instructions. Building a contract service just to relabel arrangements like these would be pointless.
Nor can contracts conjure product intent or model capability that is absent. Poor decomposition stays poor, correlated errors persist, and a faulty acceptance oracle, meaning the test or judgment deciding whether the output is right, stays faulty. Suppose the end-to-end test reuses the client's flawed mock: its green result then misses the original failure entirely.
For that reason the design deserves comparison with simpler alternatives, including a single agent or a deterministic workflow. The question is whether the extra coordination improves accepted work or controls a real risk for the workload at hand.
How to test it
No new experiment has been run for this piece. Three configurations are worth comparing: a single agent (A), multiple agents given role-based assignments (B), and multiple agents using explicit delegation contracts and the path above (C).
Fairness requires giving A, B and C identical task information and acceptance criteria, comparable tools and safety limits, matching starting environments and one declared overall resource budget. B and C share models and worker counts, and A uses a matching model where feasible. The variable under study is the delegation and coordination mechanism, with no extra capability or concealed requirements on the side.
B should keep ordinary safeguards and useful task descriptions. If it naturally grows explicit handoff agreements, record that behavior and don't forbid it. Publish the real configurations so the comparison doesn't turn into a polished implementation against a deliberately weak baseline.
Pick tasks that represent the real mix: some with independent pieces, some with sequential dependencies, some with interfaces or resources shared among workers. Trials repeat from reset environments in randomized order, and ordinary tasks stay separate from deliberately injected failures. After a pilot the configurations get frozen, held-out tasks drive the actual comparison, and uncertainty is reported per dependency structure.
Anthropic's evaluation methodology distinguishes a transcript from the environment state it leaves behind, and it assesses the model together with its harness. That marks the right place to measure: does pagination work in the combined environment? Three agents announcing they are done proves nothing.
Three primary measures apply: accepted end-to-end outcomes, the total cost of each accepted outcome, and the elapsed time until acceptance. Costs include failed trials, coordination, retries, review, setup and writing the contracts. Initial setup is reported apart from recurring cost, any amortization assumption is stated, and human time is logged openly. If nothing is accepted, state the spend and zero successes instead of showing a unit cost that looks finite but misleads.
Next to these, track integration failures, duplicated work, stale-input failures, human interventions, scope violations and results that were rejected after being reported complete. Attempted and successful violations get reported separately, and unfinished trials and timeouts stay in so that fast successes don't hide long failures.
Rejecting a stale patch correctly proves a control functions, but the product task has still failed unless a valid result is accepted inside the budget. Early pilot results only indicate direction. Should contracts add overhead without better accepted outcomes or meaningfully lower risk, the sensible advice is to skip them for that workload.
Start with one handoff you can inspect
A sensible start is a single existing workflow with two workers and a named acceptance owner. The integration check stays beyond the workers' control, and each failure case gets tested alone before the scope widens. A brief along these lines can go to a coding agent:
Add the minimum delegation contract to [WORKFLOW].
Acceptance owner: [OWNER].
Preserve existing safety boundaries.
1. Inspect current delegation, inputs, permissions, and acceptance.
Exit: map who assigns, executes, checks, accepts, and commits.
2. Identify missing boundaries; reuse existing issues and checks.
Exit: owner-approved scope, revisions, deliverable, and criteria.
3. Wire the minimum contract into dispatch and result handling.
Exit: references resolve; proposals cannot accept themselves; unauthorized operations are blocked by the actual runtime.
4. Exercise valid and invalid handoffs in isolated fixtures.
Exit: demonstrate acceptance, conflict rejection, stale-input detection, missing-evidence rejection, interruption recovery, bounded retries, and authority escalation. Mock external effects.
5. Report changed files, commands run, outcomes, and remaining gaps.
Exit: distinguish implemented controls from unverified behavior.
Do not replace the orchestration platform or change unrelated work, and do not publish, deploy or broaden permissions.
The API, the client and the tests still depend on capable workers. The change lies in the operating rule around them. Before the combined work counts as complete, spell out what each contribution must fit, who may accept it, and what happens if it can't be accepted. Job titles never draw that boundary.