Skip to main content
Glama

Core 4/4: Place the order

place_order
DestructiveIdempotent

Commit a buyer to a quoted purchase under their mandate; the mandate engine returns ordered, pending approval, or refused, and idempotency keys prevent duplicate orders on retry.

Instructions

Order a quote under a mandate. This is the only call that commits the buyer to a purchase.

The mandate engine decides, not you: status ordered (silent/notify), pending_approval (a human must approve at approval_url; poll get_order) or refused (decision.findings say which rule fired). Always send an idempotency_key and reuse it on retries: the same key never orders twice (the retry returns the original order); reusing a key for a different quote fails with idempotency_key_reused. Returns the order (schema /schemas/order.json): id (PO-...), status, decision {outcome, findings}, lines, totals, approval_url when pending, receipt_jws (signed receipt) and, once ordered, erp (the hand-off to Valio Aimo's order system). In this demo erp.status is "simulated" with a SIM- confirmation_id: tell the buyer the order is placed with Sous and the Valio hand-off is simulated, not that Valio confirmed it. rationale: one sentence on why the buyer needs this order; the approver sees it next to the mandate's findings. declared_risks: optional, up to 5 short doubts of your own (as in request_quote); each holds the order for a human. buyer_request: the buyer's own message, verbatim, if you didn't pass it to request_quote (checked the same way). agent_id: optional when your credential covers mandate_id (see my_mandates). agent_token: only if you can't send the Authorization: Bearer header and the mandate requires agent auth.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "mandate_id": "<mandate_id>",
      "quote_id": "<quote_id>"
    },
    "name": "place_order"
  }
}

Input Schema

NameRequiredDescriptionDefault
agent_idNo
quote_idYes
rationaleNo
mandate_idYes
agent_tokenNo
buyer_requestNo
declared_risksNo
idempotency_keyNo

Output Schema

NameRequiredDescriptionDefault
idYes
erpNoHand-off to Valio Aimo's order system (unsigned): {adapter: stub|http, simulated, status: pending|sent|confirmed|simulated|failed, confirmation_id, note, ...}. simulated=true (status 'simulated', confirmation_id 'SIM-...'): no real order was sent to Valio Aimo (no order API in this demo); describe the order as 'placed with Sous; Valio hand-off simulated in this demo', never as confirmed by Valio.
buyerYes
linesYes
statusYes
agent_idYes
approvalNo
decisionYes
quote_idYes
order_urlYes
amendmentsNoValio's post-order exceptions (short_pick, delay, substitution_at_pick, cancel_line), each {id, kind, line, reason, tier, findings[], status: applied|pending_buyer|accepted|rejected, effect, resolution, jws (typ sous-amendment+jws)}
created_atYes
mandate_idYes
updated_atYes
agent_claimNoget_order: the agent's rationale, labelled unverified
receipt_jwsYes
approval_urlNo
credit_notesNoCredit (or extra charge) lines from amendments
total_ex_vatYes
delivery_dateYes
total_inc_vatYes
agent_rationaleNo
idempotency_keyNo
requested_delivery_dateYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.2.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructive/idempotent/openWorld; the description goes far beyond them by explaining the three possible mandate outcomes, that a human approver may gate the order via approval_url, the idempotency_key contract (same key never double-orders; reuse across quotes fails with idempotency_key_reused), and that declared_risks each hold the order for a human. It also flags the demo-specific erp.status="simulated" caveat and how to phrase it to the buyer, which no structured field conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The most decision-critical facts — sole committing call and the three outcomes — are front-loaded, and nearly every sentence adds operational value. The parameter notes at the end are packed into a dense run-on block, which slightly hurts scanability but not correctness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, open-world, 8-parameter mutation with no schema descriptions, this covers the decision model, approval flow, idempotency, auth fallbacks, and the return shape reference. Return details overlap the output schema, but the demo-specific erp simulation warning is context an agent could not get elsewhere.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the load, and it does for most params: rationale (shown to the approver beside findings), declared_risks (max 5, each triggers a human hold), buyer_request (verbatim, validated the same way as in request_quote), agent_id (optional when the credential covers mandate_id), agent_token (only without a Bearer header), and the full idempotency_key semantics. mandate_id and quote_id receive no explicit definition beyond the surrounding narrative, leaving a small gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Order a quote under a mandate. This is the only call that commits the buyer to a purchase." names a specific verb and resource and explicitly distinguishes this tool from the non-committing siblings (request_quote, can_i_order) without needing their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the triggering context (a quote under a mandate), what to do when the outcome is pending_approval (poll get_order), and when to use the agent_id/agent_token fallbacks (see my_mandates). It does not explicitly say whether can_i_order should be called first as a pre-check, so routing to that sibling is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.