Skip to content
DocumentationBuild a bounded agent
On this page

Page resources

Open Markdownllms.txtView source

Last updated

This recipe follows the checked support-triage agent, which receives a bounded policy lookup tool and one ticket-escalation effect. The .one excerpt mirrors the current owning example; the focused Rust APIs are illustrative end-product syntax.

1. Declare the agent contract

one 1

semantic example.support
    domain one.agent@1
    agent SupportTriage@1
        instructions "Triage support requests using policy evidence before escalation."
        interface
            one shot example.support#Triage.Run@1
            start example.support#Triage.Start@1
            turn example.support#Triage.Turn@1
            resume example.support#Triage.Resume@1
        tool lookup_policy uses example.support#Policy.Lookup@1
        tool escalate_ticket uses example.support#Tickets.Escalate@1
        context request
        context completed turns
        context tool results
        model
            text true
            tool calling true
            streaming true
        budget
            input tokens 10000
            output tokens 1000
            cost microunits 10000
            elapsed 10s
            context bytes 65536
            tool calls 4
            child agents 0
            network bytes 0
            effects 1
        retention encrypted
        delegation maximum children 0

The prompt does not grant authority. The selected session fixes subject scope, principal, tools, disclosure, budgets, provider binding, and delegation before the model sees any context.

2. Keep tools typed

#[one::agent::tool(claims::LookupPolicy)]
async fn lookup_policy(ctx: ToolContext, input: TriageRequest)
    -> ToolResult<TriageResponse>
{
    ctx.operations().policy().lookup(input).await
}

#[one::agent::tool(claims::EscalateTicket)]
async fn escalate_ticket(
    ctx: ToolContext,
    request: TriageRequest,
) -> ToolResult<TriageResponse> {
    ctx.operations().tickets().escalate(request).await
}

The model calls versioned operations and receives typed results, progress, faults, approval suspension, and evidence references. It never emits shell text that bypasses the operation boundary.

3. Separate proposal from effect

{
  "subject": "ticket/support-7391",
  "operation": "example.support#Tickets.Escalate@1",
  "reason": "policy-requires-human-review",
  "authority": "approval-required",
  "expires_at": "2027-01-15T12:00:00Z"
}

The approval view displays the exact operation, subject, amount, disclosed data, provider, cost, expiry, and blast radius. Approval authorizes only that exact request under a fresh grant; editing the amount produces a new proposal.

4. Suspend and resume exactly

match agent.run(case).await {
    AgentRun::Completed(answer) => publish(answer),
    AgentRun::AwaitingApproval(request) => suspend(request),
    AgentRun::BudgetExhausted(usage) => hand_off(usage),
    AgentRun::Cancelled(reason) => record_cancel(reason),
    AgentRun::OutcomeUnknown(effect) => reconcile(effect),
}

Resumption uses retained agent, tool, approval, and resource events. It does not reconstruct authority from conversation text or repeat completed tools.

5. Select the model independently

cargo test -p support-triage-agent --all-targets --offline
cargo run -p support-triage-agent --offline

Planning can select a local or hosted model only if its data handling, retention, region, context limits, tool behavior, price, identity, and evidence satisfy the root. Model quality informs selection but never grants a tool.

Executable evidence

The checked-in support-triage project proves source/Rust parity, exact tool closure, a two-call tool trace, one admitted effect, bounded events and usage, deterministic inference, durable encrypted session selection, release, History facts, and idempotent resume.

See agents and automation and workflows and agents.