DEV Community

Danil Galeev
Danil Galeev

Posted on

Typed Contracts Between AI Agents: The Interface That Actually Breaks

Most multi-agent failures I've seen don't happen inside an agent. They happen between two of them.

When the handoff between two agents is treated as loosely structured JSON or implicit shared state, the interface is underspecified — and underspecified interfaces fail quietly.

A production handoff should be treated like any other API contract:

  • an explicit input schema;
  • an explicit output schema;
  • required and optional fields;
  • semantic constraints, not only valid JSON;
  • a clear rejection and fallback path.

A concrete example

A research agent should not hand an unstructured object to a scoring agent. It should emit something the scorer can actually validate:

class ResearchResult(BaseModel):
    subject_id: str
    evidence: list[EvidenceItem] = Field(min_length=1)
    source_count: int = Field(ge=1)
    confidence: float = Field(ge=0, le=1)
Enter fullscreen mode Exit fullscreen mode

The scorer runs only after that result passes validation. That gate is the important part.

Probabilistic output, consequential action

An LLM output is probabilistic. A database write, an external message, or a business decision is an action. Those two steps should not be directly coupled.

Between them, put a deterministic gate:

  1. Parse the model output.
  2. Validate its schema and business rules.
  3. Reject, retry, route to review, or stop the branch when validation fails.
  4. Execute the action only on an accepted contract.
  5. Record the handoff version and validation result.

Why it changes failure behavior

Without a contract, a missing field becomes a null value, the null becomes a misleading score, and the score becomes a bad CRM update. The symptom shows up several steps away from the cause, and by then the trail is cold.

With contracts, the same failure is localized: ResearchAgent -> ScoringAgent, field source_count, validation rule failed.

That is more than defensive programming. It is architecture for software systems whose internal steps are non-deterministic.

It gives staff engineers independently testable boundaries, helps principal engineers reduce coupling between teams and agents, and gives architects and CTOs a clearer way to reason about compatibility, ownership, and recovery.

The rule

Every probabilistic step that feeds a consequential action needs an explicit validation gate. Typed contracts are one strong way to define that boundary.

The model can be creative inside the boundary. The boundary should not be.

Where have you found the most valuable contract in an agent workflow — between agents, between an agent and a tool, or before the final action?

Top comments (2)

Collapse
 
jo-do profile image
Jo Do

Versioning the handoff is necessary, but I would also preserve unknown fields and the producer's raw artifact. Agents evolve at different speeds, and a strict parser that silently drops a new provenance field is worse than a clean rejection. Forward-compatible envelopes plus version-specific semantic validation make rolling upgrades much less dangerous.

Collapse
 
hannune profile image
Tae Kim

The version recording is the piece we ignored the longest. We bumped a research agent once without updating the downstream scoring schema, and the scorer kept running because the top-level fields still validated fine - the issue only showed up two weeks later when someone actually looked at the score distributions and they'd been silently off. The hardest contract to add in our case was the one closest to the database write, because that's where the team had the most "this has always worked" confidence. The "model can be creative inside the boundary, the boundary should not be" framing is the one I'd use to get buy-in.