Skip to main content
A proposal agent answers buyers’ proposal requests for a seller. When a seller wants its own model to answer, instead of Chef, it connects that model to Apostra as a proposal agent with save_agent.
For now, only Apostra’s own accounts in the modular sales agent beta can register a proposal agent. Any other account, including a seller in the beta, that sends kind: "proposal" gets FEATURE_NOT_ENABLED with details.reason own_proposal_agent_unavailable, for a dryRun: true preview too, before Apostra reads the agent. For such an account, an agent that answers the four proposal tasks reads as a sales agent, and every other kind of agent connects as before. Registering your own opens to sellers later, as its own release, when you can choose which agent answers your buyers’ proposal requests.

What changes for buyers

Nothing yet. Chef still answers every proposal request until routing to a seller’s own agent is available. Connecting a proposal agent registers it and checks it; it does not send it any buyer’s request. Choosing it is a separate setting: save_seller with proposalAgent.answering set to own and the agent’s id in proposalAgent.ownAgentId. Choosing own is also open only to Apostra’s own accounts for now. See Choose the brain that answers your buyers.

What the agent must answer

Apostra reads the agent’s get_adcp_capabilities without credentials and connects it as a proposal agent only when:
  • supported_protocols contains media_buy, and
  • media_buy.lifecycle_tools lists all four proposal tasks: request_proposals, refine_proposals, decline_proposals and accept_proposal.
When a task is missing, the call is refused with VALIDATION_ERROR. details.reason is proposal_tasks_missing and details.missingTasks names each task the agent does not list. Add them to the agent and try again. An agent that also lists control_media_buy reads as a sales agent that also answers proposals, so its preview shows kind: "sales" with proposal in alternativeKinds. An agent without it reads as a proposal agent, with sales as the alternative. Either way, send kind: "proposal" to connect it as a proposal agent. get_adcp_capabilities must answer without credentials. Apostra does not connect a proposal agent it could not read, because it cannot check the four tasks.

Who can connect one

For now, only Apostra’s own accounts in the beta qualify (see the note above). In such an account, a person who directly administers it, signed in as themselves: Service tokens, delegated sessions and impersonation cannot connect an agent.

Connect it

First preview what Apostra reads. Nothing is saved:
The preview returns the reading and inferred.kind: "proposal". Then connect it with an idempotencyKey, so a retry finds the first agent instead of making a second one:
You may send displayName to replace the name Apostra suggests. A proposal agent has no sales mode and no first test.

The credential Apostra presents

When Apostra calls your proposal agent, it presents a credential you enter on the agent’s page in the web app, never in chat. Do not paste a credential into a conversation. Entering it on the agent’s page is coming soon.

Prove the agent is yours

Like every connected agent, a proposal agent is not verified as yours until the brand.json on its own host lists it. AdCP’s brand.json has no proposal agent type, so list a proposal agent with "type": "sales":
Everything else follows the same rules as any agent: the exact URL, the file on the agent’s own host, and a host on a domain your organization has verified. See Prove your agent is yours.