← All writing

Essay

The agent API is no longer an endpoint

Traditional APIs expose one operation at a time. Agent-native APIs need a bounded, inspectable contract for the complete job.

The agent API is no longer an endpoint — SproutPad

When we first gave agents access to SproutPad, the obvious unit of design was a tool call. Search for a domain. Estimate a launch. Create a server. Each request was small enough for the API to authenticate, validate, execute, and describe honestly.

Then we started looking at the job the agent believed it was doing: "put this project online." That job might include a domain, hosting, DNS, a certificate, and a mailbox. The API could see each request as it arrived, but it could not see that larger intent before the first effect.

Application code, workflow engines, and runbooks have always carried this missing layer. With an agent, it can exist only inside a model turn. That should make an infrastructure designer uncomfortable.

A collection of buttons is not a plan

MCP made tools easier for agents to discover and call. REST remains a useful wire interface. SDKs add types. A CLI fits naturally into a coding agent's shell. These are good entrances.

They do not answer what should happen between calls.

If the agent owns the workflow privately, the server cannot inspect the whole job before it starts. A human may approve one purchase without seeing the dependent actions around it. A retry may reconstruct a slightly different sequence. A policy change halfway through may be noticed by one operation and missed by client-side glue. After a partial failure, the agent has to infer which effects really occurred from a mixture of responses and lost connections.

This is not a complaint about careless agents. We handed a probabilistic caller a bag of operations and quietly made it the transaction coordinator for systems that do not share a transaction. I do not think that is a reasonable contract.

Traditional APIs assume the caller supplies reliable orchestration. An agent-native API should not quietly inherit that assumption.

A six-step agent-plan lifecycle: the agent proposes a complete bounded job; SproutPad validates and freezes it without product effects; the plan is inspected; apply rechecks current authority and state; each node runs through durable governance and human gates; receipts and verified outcomes are retained.
The agent proposes the job. SproutPad freezes the plan, checks current authority as it runs, and records the real outcome. Open full-size diagram

Let the agent propose the job

Our current design gives consequential composition its own public contract. The useful part is not that the data structure happens to be a graph. It is that the server gets to inspect the whole proposed job before anything lasting happens.

The agent submits a finite graph of operations: named steps, literal arguments, dependencies, cost bounds, expected versions, stable idempotency identities, and any reviewed compensation relationship. The operations come from a server-owned allowlist. The agent cannot invent a handler, include a program, download a package, interpolate a previous result, or ask us to execute a URL.

Preparation validates that draft, fills server-owned defaults, computes the worst-case spend, binds the visible projects and required scopes, and persists one canonical signed representation. We deliberately made this phase a little boring: it produces an object to inspect, not an effect to explain away later.

Preparation does not execute the plan. It does not reserve money, create a human gate, start a task, mutate a provider, or quietly turn a quote into a commitment. Its product effect is limited to creating an immutable plan that can be inspected.

That separation matters. "Tell me what would happen" should not consume the authority required to make it happen.

The signature freezes meaning, not permission

Calling the result a signed plan creates an easy misunderstanding.

The signature proves that SproutPad produced those exact plan bytes and that they have not changed. It does not authorize the plan. It is not a bearer credential, policy verdict, budget reservation, human approval, provider receipt, or proof that the expected state still exists.

Apply is a separate direct operation. It authenticates the current caller, checks tenant and project boundaries, verifies the signature and expiry, recomputes price and budget constraints, and compares current resource state with the plan's version fences.

The checks continue after admission. Before a consequential node runs, it enters the same policy, budget, idempotency, provider-intent, and receipt path used by the corresponding direct API operation. A successful preparation from ten minutes ago cannot freeze today's permission or make stale state current.

We use the phrase server-attested action plan in ordinary product copy because it keeps these roles separate:

  • the plan says what was proposed;
  • the signature says those bytes are unchanged;
  • current authority decides whether the next effect may occur;
  • the receipt says what actually happened.

We could have called the result an "authorized workflow token" and saved a few API concepts. We did not, because that shorter interface smuggles a stale authorization decision into a portable object.

Durable work needs an identity outside the conversation

Applying a plan creates one durable task and admits one durable workflow.

That identity matters more than the connection that carried the request. The model turn can end. The CLI can time out. The network can fail after admission but before the response arrives. A worker can restart while waiting for DNS or a person.

None of those events should turn "I did not observe the result" into "the job did not start." The caller reuses its apply idempotency key, receives the same task, and observes durable state.

Human approval is part of that state without becoming agent authority. A plan may identify a step that can require a person, but it cannot approve the step. When execution reaches the boundary, the durable job pauses. An authorized person reviews the current action, price, and consequences on the signed-in surface. The database decision is the authority; a workflow signal only wakes the waiter.

The agent gets a status to observe, not an approval capability to exercise.

A graph does not make providers transactional

Putting several operations in one plan does not give us a distributed transaction.

A registrar may accept a purchase before the response is lost. A DNS provider may succeed while certificate work fails. A compensation attempt may itself time out. Some effects, such as registering a domain or sending mail, cannot be made not to have happened.

For that reason, every node needs an honest outcome and any compensation must be another governed operation. The plan can finish successfully, fail before an effect, retain a completed effect, compensate under reviewed conditions, remain compensation-pending, or require manual reconciliation.

"Rolled back" is not a synonym for "the workflow returned an error."

The final record includes node attempts, real provider references, actual costs, approval decisions, compensation outcomes, and verification evidence. An accepted workflow start is evidence of admission. It is not evidence that the intended public state exists.

The operation contract is the foundation

A workflow compiler is only as trustworthy as the operations it composes.

At SproutPad, MCP, REST, the TypeScript SDK, and the CLI are being projected from one canonical operation contract. The contract records schemas, effect, idempotency, task behavior, approval behavior, and public bindings. Workflow eligibility is a narrower, reviewed allowlist over that catalog.

The division we settled on is:

  • the operation contract defines what each action means;
  • the compiler owns graph shape, dependencies, and immutable plan identity;
  • the durable runtime owns progress and recovery;
  • the governor owns authority, exposure, gates, fencing, and receipts;
  • conformance checks whether a named build preserves those claims.

No client interface gets to become a second control plane. No workflow compiler gets to become a second authorization system.

What comes after MCP

The first generation of agent integrations asked whether a model could call the product. The next generation has to ask harder questions.

Can the agent show the complete job before it starts? Can the job survive the agent? Can a person interrupt it without becoming an API token? Can the server reject a stale step even when the original plan was valid? Can another system distinguish admission, execution, and verified effect?

That is the larger agent-infrastructure problem.

We are implementing one answer in SproutPad and turning the reusable parts into an open, testable contract for agent actions. It is not a standard because we call it one. The contract has to be published, the implementation has to pass its own checks, and another implementation eventually has to pass them too.

MCP is still a useful front door. The agent API is the room behind it: the operation contract, the plan, the durable task, the authority boundary, and the evidence left when the work is over.

The live production contract is available at sproutpad.ai/openapi.json. That contract, not this essay, is the source of truth for what an agent can call today. The production build's signed conformance history is available at sproutpad.ai/conformance.