Governed Agentic Decision
A Touba agentic decision is a choice made within a declared scope. The runtime does not ask the host to decide on its behalf, and it does not grant unbounded freedom to the agent.
user objective
-> Touba agent
-> controlled model input
-> capabilities authorized by AIR
-> configured decision provider
-> structured selection
-> runtime verification
-> execution or refusal
-> trace
What the Runtime Does
When execution reaches an agent, the runtime:
- reads the capabilities declared in
uses; - builds a structured model input;
- separates developer instruction, user data, external content, and the resource interface;
- indicates that a capability catalog is available;
- sends the full catalog only if the provider requests it;
- may accept a direct answer if no capability is needed;
- receives a
target_refand, when needed, arguments; - verifies that the target belongs to
uses; - verifies
callable_byif the target is another agent; - verifies that arguments match the target signature;
- executes the capability, returns the direct answer, or refuses before any handler;
- returns the intermediate result to the model as an observation for the next decision;
- traces the decision.
This loop reduces host-side burden: the host no longer has to rebuild the catalog manually, extract a choice, verify scope, and inject the decision back into Touba.
Two Provider Representations, One Runtime Authority
The SDK can represent the model choice in two ways:
| Interface | Provider representation |
|---|---|
structured | decision object produced from a schema; the default behavior |
native | native function call during the catalog phase; an explicit host choice |
This difference changes neither .tb syntax, AIR, nor the
touba-agent-decision-v1 protocol. With the native interface, the SDK gives the
model no executor: it normalizes the proposal, then the runtime applies the
same controls and performs execution itself.
The native calls under Touba authority tutorial shows the configuration and complete cycle.
On-Demand Catalog
The runtime does not necessarily transmit every contract at every decision.
First exchange:
{
"protocol": "touba-agent-decision-v1",
"mode": "summary",
"model_input": {
"protocol": "touba-agent-model-input-v1",
"mode": "orientation",
"developer_instruction": {
"source": "air_agent_responsibility",
"text": "Find and summarize public datasets."
},
"content_boundary": {
"developer_instruction_authority": "instruction",
"user_input_authority": "domain_data_only",
"external_content_authority": "untrusted_content"
},
"user_input": {
"category": "domain_data",
"keys": ["request"]
},
"resources_hint": {
"capabilities_available": true,
"capability_count": 2,
"catalog_available_on_request": true
}
},
"agent_ref": "agent:examples.research/Researcher",
"capability_count": 2,
"capability_refs": [
"skill:examples.research/SearchDatasetOnly",
"skill:examples.research/BuildDatasetBrief"
],
"input_keys": ["request"]
}
For a simple input such as a greeting, the provider can answer without requesting the catalog:
{
"action": "answer_directly",
"source": "ai_sdk_structured_output",
"reason": "No Touba resource is required.",
"result": "Hello."
}
If the provider needs details, it responds:
{
"action": "request_capabilities",
"source": "ai_sdk_structured_output",
"reason": "I need to compare the available contracts."
}
The runtime then sends the authorized catalog: kind, signatures, local type fields, output type, required grants, secret handles, memory access, and sub-capabilities. A capability can be a function, tool, skill, agent, or strategy when it is declared in uses. Every capability exposed to the provider must have an explicit source description; otherwise the runtime refuses before the model call. This gives the provider stable semantic signal without weakening runtime verification.
For an agent exposed to another agent, the catalog can include its responsibility, summarized sub-capabilities, and callable_by rules. This treats multi-agent delegation as a governed capability, not as an open call.
Sequential Loop
An agent can consume multiple resources during the same run. After each authorized resource, the runtime returns an observation to the model:
{
"agent_state": {
"step_index": 1,
"observation_count": 1,
"observations": [
{
"target_ref": "skill:examples.research/SearchDatasetOnly",
"result": {
"datasets_count": 3
}
}
]
}
}
The observation is used to decide the next step: answer, request the catalog, call another authorized capability, or request human review. Traces indicate that a result is available, but they do not write the raw observation.
Selection with Arguments
The provider can select a capability and fill its inputs:
{
"action": "select_capability",
"target_ref": "skill:examples.research/BuildDatasetBrief",
"source": "openai_structured_output",
"reason": "The request requires search followed by summarization.",
"arguments": {
"request": {
"query": "firefighter",
"rows": 1,
"dry_run": true,
"llm_model": "gpt-4.1-nano",
"goal": "Find a public dataset and produce a short summary in English."
}
}
}
The runtime verifies that BuildDatasetBrief belongs to uses. It also verifies that request is an input declared by the capability. An unknown or missing input causes refusal before execution.
Human Review Requested by the Agent
The model can request human review in catalog mode:
{
"action": "request_human_review",
"target_ref": "human_review",
"source": "openai_structured_output",
"reason": "The result should be confirmed before continuing.",
"review_prompt": "Validate the selected dataset before synthesis."
}
This mechanism differs from human.approve. human.approve is a barrier imposed by the program. request_human_review is an option the agent may request; the runtime pauses when no human decision is available, then resumes only with an explicit decision.
JavaScript Provider
@touba/sdk provides an adapter for the AI SDK:
import { createAiSdkDecisionProvider } from "@touba/sdk";
import { model } from "./model-provider.mjs";
export const decideAgentCapability = createAiSdkDecisionProvider({
model,
});
export const provider_metadata = {
provider_kind: "sdk_ai",
provider_name: "researcher-provider",
provider_version: "1.0.0",
model_family: "openai",
prompt_template_id: "researcher-v1",
decision_schema_version: "touba-agent-decision-v1",
};
Provider choice remains project-side. Touba keeps its own protocol, and the runtime revalidates the decision. The Donnees Quebec scenario uses the SDK OpenAI helper to demonstrate a real execution path with an explicitly configured provider.
The runtime traces a redacted request digest, non-secret provider metadata, provider call attempts, bounded retries, and max_provider_calls budget refusals. These traces do not expose the raw values sent to the model.
Decisions and concurrency
Each agent makes decisions sequentially. A selected capability may be a strategy
or skill containing a parallel group; a strategy can also distribute inputs
across a typed agent. Branches isolate their observations and share run budgets,
without widening uses or callable_by. An authorized capability may be reused.
The SDK's structured and native interfaces change the model-facing
representation, not runtime authority. The SDK guide
explains configuration; the multi-agent tutorial
shows composition and recovery.
Free-form session handoffs, distributed scheduling and strict monetary ceilings are not part of this mechanism.