Skip to main content

Grounding checks

A grounding check asks one Source to retrieve current trusted facts for one proposed argument value, then evaluates deterministic match conditions against the result.

order_id:
ground:
checks:
- source: billing-production
query: >-
SELECT customer_id, status
FROM orders
WHERE order_id = %(value)s
match:
- column: customer_id
ctx: customer_id
- column: status
value: delivered

Check lifecycle

The Source request and match evaluation are separate. Adapters retrieve data in different ways, but every adapter uses the same match semantics.

Bound values

Every check can bind:

  • value — the argument being grounded;
  • any scalar argument from the same proposed tool call;
  • any scalar trusted-context field.

Trusted context overrides a tool argument with the same name.

The binding syntax depends on the adapter:

AdapterExample
SQLiteWHERE order_id = :value AND customer_id = :customer_id
PostgresWHERE order_id = %(value)s AND customer_id = %(customer_id)s
MySQLWHERE order_id = %(value)s AND customer_id = %(customer_id)s
HTTP/orders/{value}?customer={customer_id}
MCParguments: {order_id: "{value}", customer: "{customer_id}"}

Do not format values into SQL strings. Use the adapter’s named parameter syntax.

Definitive mismatch

When the Source request succeeds but its result does not satisfy the match conditions, on_fail controls the outcome:

on_fail: block # block (default) or hold

A definitive mismatch is not retried. The Source has answered the question; repetition does not make the fact transient.

Use hold only when a mismatch legitimately requires human judgment. Ownership failures and missing required records should normally block.

Unreachable Source

Exceptions such as timeouts, authentication failures, server errors, invalid queries, or MCP tool errors use retry:

retry:
attempts: 2
on_error: block

attempts is the number of retries after the first request. attempts: 2 can therefore call the Source at most three times.

After retries are exhausted, on_error can be:

ValueBehavior
blockFail closed. Default and recommended for consequential actions.
holdRequire human review. The reviewer sees that verification was unavailable.
allowFail open and let this check contribute allow.
Fail-open configuration

on_error: allow converts loss of a trusted verification dependency into permission to execute. Use it only when the action’s risk model explicitly accepts that behavior and another control remains authoritative.

Retry currently has no per-attempt delay inside a check. Keep Source-level connection and statement timeouts bounded so a tool call cannot wait indefinitely.

Multiple checks

All checks across all protected arguments run and participate in one decision. One check can verify ownership in billing while another verifies absence from a refund ledger.

ground:
checks:
- source: billing-production
query: SELECT customer_id FROM orders WHERE order_id = %(value)s
match:
- column: customer_id
ctx: customer_id
- source: refund-api
path: /refunds?order_id={value}
match:
- rows: eq
value: 0

The checks are an AND: the order must belong to the caller and no prior refund may exist.