Designing Your Agent Service for Orchestrator Callers
· 787 words
When a developer calls your agent service, they read the documentation, run a test, decide it works, and integrate it. The feedback loop is fast. If something is wrong, they tell you or they leave.
When an orchestrator calls your service, the decision was made by a system that evaluated your endpoint against a policy, not a person who read your README. The orchestrator routes tasks to your service because your schema matched its requirements, your declared latency fit its SLA, and your pricing held within a budget parameter. Nobody examined your documentation. Your service either fit the criteria or it did not.
Designing for orchestrator callers means making those criteria explicit and reliable.
Declare your contract precisely
An orchestrator needs to know three things before it calls you: what inputs you accept, what outputs you produce, and what the call will cost. These need to be machine-readable, not described in prose.
Your tools/list response should include typed input schemas for every tool, not just parameter names. An orchestrator that receives an ambiguous parameter cannot ask for clarification. It either guesses the type and sends a call that may fail, or it excludes your service from routing. Typed schemas with explicit constraints eliminate that decision.
Output schemas matter equally. If your service returns different response shapes depending on internal conditions, an orchestrator receiving an unexpected shape has no fallback. It fails, logs the error, and either retries or routes the task elsewhere. A stable, versioned output contract reduces those failure paths.
Declare pricing in a queryable form, not just in documentation. An orchestrator managing budget across many services needs to forecast cost before it commits to a call. A price_estimate endpoint that accepts your input structure and returns a fee before execution is the mechanical version of a price quote. If you do not offer one, the orchestrator treats your pricing as unpredictable and may deprioritize you for budget-sensitive workflows.
Handle idempotency and retries by design
Orchestrators retry on failure. This is not configurable from your side; it is how automated systems manage transient errors. A call that fails due to a timeout will be retried, usually within seconds. If your service is not idempotent, a retry can cause duplicate actions, double charges, or corrupted state.
Accept a request ID in every call and use it as an idempotency key. If you receive the same request ID twice, return the result of the first call. Log the duplicate. Do not perform the action again.
This is not only a correctness concern. An orchestrator that discovers a service produces duplicate side effects on retry will stop routing to it. Idempotency is what distinguishes a service that can be trusted as infrastructure from one that requires careful manual oversight.
Keep error responses structured
When your service fails, the error response is machine-read. An orchestrator receiving a free-text error message cannot parse the cause, decide whether to retry, or route the task to a fallback. An orchestrator receiving a structured error with a code, a retryable flag, and a machine-readable reason can do all three automatically.
At minimum, error responses should include: whether the error is transient (retryable) or permanent, a stable error code the orchestrator can match against its routing logic, and a description the orchestrator can log without processing. The description is for human debugging; the code and flag are for the system.
Version your schema explicitly
An orchestrator integrates against your schema at evaluation time and expects it to be stable indefinitely. A schema change that breaks a calling convention causes silent failures in production workflows that may not surface immediately.
Version your tools/list response. When you need to change a schema, add a new tool version rather than modifying the existing one. Keep the old version available until you have confirmed that callers have migrated. The cost of running two versions temporarily is much lower than the cost of breaking an orchestrator's production traffic without warning.
What the orchestrator cares about that developers do not
A developer evaluates your service once and then uses it until something breaks. An orchestrator re-evaluates services continuously against current performance data. Latency drift, error rate changes, and pricing shifts are monitored and factored into routing decisions on an ongoing basis.
This means your SLA is not a promise you make at launch. It is a constraint you have to maintain in production for the orchestrator to keep routing to you. Latency that was acceptable at evaluation but degrades over time will cause the orchestrator to reduce your traffic share or remove you from the routing pool.
Operational stability is the product. The feature set got you evaluated. Reliability is what keeps you in the workflow.