Proposals and Evidence API
Read agent proposals, record a human decision, and resolve proposal evidence.
The Proposals API is the customer-facing surface over everything Brain's agents produce. It unifies money-path payment intents and non-money agent findings into one tenant-scoped, cursor-paginated feed, lets a human decide on any one of them, and resolves the typed evidence a proposal cites into readable summaries.
This is the read-and-decide half of the agent loop. Agents propose through the gated agent path; humans list, inspect, and decide here.
List proposals
GET /v1/proposals
execution:read
Get one proposal
GET /v1/proposals/{id}
execution:read
Decide on a proposal
POST /v1/proposals/{id}/decide
execution:read or payment_intent:approve, plus member authority (see below)
Resolve proposal evidence
POST /v1/evidence/resolve
execution:read
The same read model and decision service back the MCP tools proposals.list, proposals.get, proposals.decide, and evidence.resolve. HTTP and MCP share one code path, so tenant scoping, actor resolution, member authority, and the money-path approval gates behave identically on both. See MCP Tools.
List Proposals
GET /v1/proposals?type=collections&status=pending_approval&limit=25
Authorization: Bearer <tenant token>Tenant-scoped and cursor-paginated. Every filter is optional.
type
string
One of the public proposal types (see below).
status
string
Lifecycle status filter (see below).
risk_band
string
low, standard, elevated, or high.
min_confidence
number
Float in [0, 1]. Returns proposals at or above this agent confidence.
limit
integer
Page size, 1 to 100.
cursor
string
Opaque pagination cursor from a prior response's next_cursor.
Response
next_cursor is null on the last page. A money-path proposal carries a payment_intent_id and action_type; a non-money finding leaves both null. confidence and risk_band are null when the agent did not score them.
The compact fields remain stable for existing clients. The read model also returns the additive fields below for rich proposal cards:
stored_action_type
Original stored action type, for example flag_transaction, block_payment, draft_followup, or a PaymentIntent action_type.
details
Stored action fields or PaymentIntent Ledger columns shaped as proposal details. Common keys include risk_score, ranked_signals, and entity ids.
policy
Policy decision summary: decision, policy_id, policy_version, matched_rule_id, explanation, required_approvers, and trace.
presentation
Normalized UI card data: headline, recommendation, key_facts, confidence_band, policy, consequences, actions, and technical detail.
available_decisions
Semantic decisions accepted by POST /v1/proposals/{id}/decide, with labels and meanings for the current proposal type.
presentation.technical_detail always uses the six stable layer keys 1_ingest, 2_extract, 3_classify, 4_score, 5_policy, and 6_propose.
Public proposal types
vendor_risk, payment, collections, treasury, cash_forecast, dispute, compliance, revenue_intel, reconciliation, subscription, fraud_anomaly, personal_budget, financial_health, purchase_advisor, tax_prep, travel_finance, bill_management, debt_optimization, savings.
The public type is resolved deterministically:
A stored action type that is already a public proposal type is used directly.
Otherwise Brain uses the agent role or agent kind from the stored action or joined agent row.
Otherwise Brain uses the explicit stored-action map. Examples:
flag_transaction -> fraud_anomaly,block_payment -> vendor_risk,propose_match -> reconciliation,recommend_card -> travel_finance,tag_tax_item -> tax_prep,remind -> bill_management, andrecommend_savings_transfer -> savings.
Ambiguous stored action names such as notify, escalate, create_task, and recommend_action resolve through the agent role. Brain does not guess their public type from the action name alone.
This expansion is backward-compatible. No new API version or route was introduced because all compact fields remain in place and the richer fields are additive.
Lifecycle status values
proposed, pending, pending_approval, awaiting_second_approval, approved, acknowledged, reconciling, paused, dispatching, rejected, executed, failed, cancelled, undone, unknown.
Get One Proposal
Returns the same object shape as a list item. An unknown or cross-tenant id returns 404 execution_proposal_not_found; the read is tenant-scoped, so a proposal from another tenant is indistinguishable from one that does not exist.
Decide on a Proposal
decision is one of approve, reject, acknowledge, or undo.
A decision is a human authority action, not a token-scope action. The route accepts execution:read or payment_intent:approve, but it then resolves the caller through the same ProposalDecisionService as every other approval surface. The actor must be a user-principal, active tenant member with approval authority. Agent principals are rejected with actor_unresolved; a propose-only agent token can read proposals but can never decide one.
Approving a money-path proposal runs the full money-path authority gate, in order: active tenant member, admin or approver role, authorized approval domain, per-item limit, actor is not the payee (self-approval block), and a tenant-wide distinct second approver where the policy requires one. A first valid approval on a proposal that needs two moves it to awaiting_second_approval; a distinct second member's approval clears it for dispatch. The same member approving twice returns second_approval_required. Every decision is written to the Audit log before any status transition.
acknowledge records that a human saw a non-money finding without acting. reject closes a proposal. undo reverses an eligible prior decision. There is no execute call here or anywhere on the API: approval authorizes Brain's internal settlement path, it does not dispatch the rail itself.
Resolve Proposal Evidence
Proposals cite evidence as typed { kind, ref } pairs. This endpoint turns those refs into tenant-scoped summaries and deep links, so a UI can render what a proposal is standing on without knowing each ref format.
At most 50 refs per call. Response:
Resolution fails closed and is tenant-scoped. A supported ref that does not exist in the tenant returns resolvable: true, not_found: true. An unsupported kind or malformed ref returns resolvable: false with a reason of unsupported_kind or malformed_ref; it is never an error.
Resolvable kinds: account, counterparty, invoice, obligation, transaction, wiki_entity. Other evidence kinds a proposal may cite (for example document, payment_intent, policy, raw_artifact) are returned unresolved today rather than rejected, so a mixed evidence list always resolves partially instead of failing whole.
Related
How agents run and propose
The money-path proposal
The same tools over MCP
Who may approve
Last updated
