AI reference
Compact, normative Rungent context for coding agents.
Objective
Embed Rungent into an existing Python application. Define one Agent, typed @tool functions, a
Runtime, application identity/context factories, and the FastAPI router. Use @rungent/sdk in the
frontend. Never implement another tool loop.
Canonical imports
from rungent import (
Agent,
DeferredRequest,
Identity,
InteractionRequest,
Runtime,
RunActivity,
ToolContext,
ToolContinuation,
ToolResult,
tool,
)
from rungent.fastapi import create_router
from rungent.mcp import create_mcp_asgi
from rungent.llm import OpenAICompatibleModel
from rungent.sqlalchemy import RungentBase, SQLAlchemyStore
from rungent.testing import BaselineCase, BaselineSuite, ScriptedModel, run_baselineRequired invariants
- Tool parameter types are mandatory; the first parameter is
ToolContext. effectandapprovalmust be explicit on every business tool.approval="always"requires a concreteconfirmationstring or callable, then freezes and gates the exact invocation. Never use a generic title as the approval prompt.- Use one
formfor independent, already-known questions; ask sequentially only when later questions depend on earlier answers. Do not ask for approval in plain assistant text. - Choice interactions declare
multiple,allow_custom, and safeallow_skip; clients submit{selected: string[], custom?: string, skipped?: boolean}and the runtime validates it before resuming. - Form interactions contain 1–8 typed questions; clients submit
{answers: {question_id: string | ChoiceResponse}}once. report_progressis a reserved built-in tool for short, public updates during multi-step work. It is not raw reasoning and has no business side effect.- Long-running host tools call
await ctx.report_progress(message, public=...)to persist and stream real application progress before the tool completes. All updates from one tool call use a stable activity ID and project as one changing SDK activity while the persisted event stream retains every update. The activity remainsrunninguntil the tool succeeds or fails. - An Agent may declare a host-authored
run_activity(ctx, content)provider. Rungent emits itsRunActivityimmediately, then updates the same persisted running activity after three silent seconds and every five seconds until the model stream advances. These are public working states, never provider reasoning or hidden chain of thought. Runtime.model_step_timeout_secondsbounds each provider attempt andmodel_step_total_timeout_secondsoptionally bounds the complete model step. Retries receive a fresh per-attempt budget; timeout persistsrun.failedthrough the normal terminal path.ToolResult.datais model-visible,messageis safe progress text, andpublicis optional UI data.ToolResult.interactionmay contain a typedInteractionRequestand frozen continuation tool. Rungent validates and persists it, then directly invokes therequires_interaction_responsecontinuation after the user answers without another model step. Model-facing results have an explicittool_status: success|errorenvelope;data.ok=false, exceptions, timeouts, and validation errors are failures and may be retried. A failedToolResultmay use its safemessageas the public failure activity; exception details remain private.ToolResult.deferred=DeferredRequest(...)pauses a successful tool inwaiting_externalwithout completing its activity or spending another model step. The host reports safe progress and callsRuntime.resume_deferredwith the authoritative terminalToolResult. Rungent atomically claims and leases the resumed execution before returning to the model, so recovery workers cannot classify the active continuation as interrupted; task IDs are bound to one Run and can be consumed once. Useexternal_task_cancellerto connect Run cancellation to host-owned work.- After a validated non-approval response,
ToolContext.interaction_responseexposes its ID, kind, original prompt, and normalized value to host tools for trusted sequential workflows. Declarerequires_interaction_response=Trueon tools that consume it; Rungent hides those tools before a real response and clears the trusted response after the first attempted consumption. - Equivalent successful non-read calls are deduplicated within a Run after argument normalization.
Use an explicit batch/count argument; set
deduplicate=Falseonly for genuinely repeatable writes. - Sessions are owned by
Identity; identity resolution belongs to the host application. create_mcp_asgiinvokes exportable tools (requires_interaction_responseis omitted). It does not use Runtime, ACS, orrequest_input. Host code owns OAuth.Agent.export_skill()is a markdown draft, not a router.- One session has at most one active Run; resume the waiting Run instead of starting another.
- ACS
seqis monotonic for the complete Run, including every pause/resume cycle. - Model step IDs and the 16-step default budget are also monotonic across pause/resume cycles; provider retries do not consume additional model steps.
- A provider completion with neither text nor tool calls is retried by the bounded harness loop; it never becomes a successful empty assistant message.
- The model transport retries timeouts, network failures, HTTP 408/429, and 5xx responses three
times by default. Retries stay in the same model step and emit
message.resetplusmodel.retrying; clients replace partial output and showretry/max_retriesprogress. - Malformed or truncated tool-argument JSON follows the same bounded retry path with reason
invalid_tool_arguments. The retry adds a compact-valid-JSON correction and cannot execute a partial tool call. - Public ACS events are persisted before delivery. Never expose or persist provider
reasoning_content, hidden chain of thought, private tool data, or exception details. - Dynamic business state comes from
Agent.context, not stale conversation prose. - Production uses
SQLAlchemyStoreand an application Alembic migration. - Frontends consume ACS through
@rungent/sdk. - Terminal events settle unfinished activities; call SDK
failRungentStatefor transport failures. - Every integration ships deterministic and real-model baseline cases.
OpenAICompatibleModel(extra_body=...)adds trusted provider-specific top-level request fields and cannot override core request fields.
HTTP contract
POST /sessions
GET /sessions
PATCH /sessions/{session_id}
GET /sessions/{session_id}
GET /sessions/{session_id}/runs
POST /sessions/{session_id}/runs
GET /runs/{run_id}/events?after_seq={seq}
GET /runs/{run_id}/events/stream?after_seq={seq}
POST /runs/{run_id}/responses
POST /runs/{run_id}/cancel
POST /mcp # JSON-RPC initialize, tools/list, tools/callACS envelope
{
"v": 1,
"id": "evt_...",
"seq": 4,
"type": "interaction.requested",
"session_id": "ses_...",
"run_id": "run_...",
"created_at": "2026-08-03T00:00:00Z",
"data": {}
}The public lifecycle is run.started, optional host-authored running activity.updated, repeated
model.started / optional model-wait activity.updated / optional model.retrying /
model.completed steps, activity.updated, tool, interaction, and external-task events, message
events, and a terminal run.completed or run.failed. A deferred tool emits
external_task.started, run.waiting_external, zero or more external_task.progress events, then
a trusted external_task.completed|failed|cancelled. Frontends render this as a work timeline and
may collapse it after completion.
Text interactions containing two or more numbered alternatives are rejected as
invalid_interaction; callers must use a typed choice so clients can render real options and the
standard custom-answer row. Tool activities expose their stable failure code to SDK consumers.
run.failed may include a stable code and retryable flag. Bounded-loop exhaustion uses
model_step_limit_exceeded; the TypeScript reducer projects these fields as errorCode and
retryable, while the configured numeric limit remains internal.