Manifest Reference
The manifest connects tools to host handlers and can explicitly activate triggers. It is supplied explicitly to the runtime.
In a Touba project, touba prepare can generate or verify the manifest from AIR. This does not change the runtime contract: execution with a tool still requires --manifest.
The handler is launched without an implicit shell and with a minimal
environment. For a JavaScript handler, touba prepare therefore writes the
absolute path of the current Node executable into handler.command.
Minimal Shape
{
"manifest_version": "touba-manifest-v1",
"bindings": {
"tool:examples.search/SearchDatasets": {
"handler": {
"kind": "process",
"command": "/absolute/path/to/node",
"args": ["handlers/search_datasets.handler.mjs"],
"cwd": "."
},
"grants": ["network"],
"effect_contract": { "kind": "none" },
"sandbox": {
"required": true
},
"timeout_ms": 5000,
"max_payload_bytes": 1048576
}
}
}
Fields
| Field | Role |
|---|---|
manifest_version | manifest version |
bindings | explicit tool -> binding table |
triggers | explicit trigger -> activation table |
run_limits | autonomy budgets applicable to the run |
handler.kind | process |
handler.command | executable launched without an implicit shell |
handler.args | process arguments |
handler.cwd | optional working directory |
grants | explicitly granted capabilities |
sandbox | platform isolation required for the handler process |
secrets | granted secret handles |
memories | granted memory access |
timeout_ms | process timeout |
max_payload_bytes | payload limit |
Explicit effect contract
touba-manifest-v1 is the only admitted format. Every binding must declare
effect_contract: { "kind": "none" } for a non-writing operation, or
{ "kind": "external_write", "retry_mode": "none" } for an external write
without safe retry support. The other retry modes, idempotency_key and
reconcile, require real support from the external service.
An external write may also declare compensation: { "entry_ref": "strategy:orders/CancelOrder" }. The inverse must be an eligible strategy
in the exact AIR and remains subject to its own authority checks.
The generator leaves effect_contract: null until the developer reviews the
handler behavior. This draft is not executable. Unknown fields, missing
contracts and retired formats are refused before dispatch. CLI writes require
--effect-journal <path.effect-journal.sqlite>; JavaScript runs use the
effectJournal option. All handlers use touba-tool-handler-v1, with
operation: invoke or operation: compensate.
Secrets
Secrets are handles. The manifest does not contain values.
"secrets": ["OPENAI_API_KEY"]
Agent Secret Scopes
{
"agent_secret_scopes": {
"agent:examples/Researcher": ["OPENAI_API_KEY"]
}
}
If the handle is absent from the active agent scope, the runtime refuses before the handler.
Memories
"memories": [
{ "ref": "memory:examples/ProjectKnowledge", "access": "read" }
]
The runtime crosses AIR, manifest, and active owner before dispatch.
Handler Isolation
A binding can require platform isolation:
"sandbox": {
"required": true,
"profile": "default"
}
When sandbox.required: true, macOS uses sandbox-exec; Linux x64 combines
bubblewrap, seccomp and the native touba-sandbox launcher with Landlock ABI 3
or newer. Out-of-scope data, writes, descendants and network connections are
denied by default. Native Linux checks cover Ubuntu 24.04, Node and Python,
including termination of descendants on timeout.
On Linux, bubblewrap must be installed and user namespaces available. An Ubuntu
host protected by AppArmor may require an administrator profile limited to that
binary, without disabling global protections. Each write_paths entry must
already exist: use a dedicated output directory to create files. Write access
does not grant read access. Exact Unix socket scopes require Landlock ABI 9;
an unenforceable policy is refused before launch. The probe runs a command
under confinement to check prerequisites.
The Windows backend is still undergoing V1 qualification, including asynchronous
Python handlers without network authorization. It is not announced as available
in a finalized distribution. An unavailable sandbox or unsupported policy
prevents execution, with no direct-execution fallback. Without a required
sandbox, handlers remain trusted host code.
HandlerSandboxUnsupportedPolicy identifies a policy unsupported by the
selected backend.
Paths are relative to the handler's cwd or absolute. Use an absolute
interpreter path (the node alias resolves to Touba's Node executable).
| Field | Required grant | Scope |
|---|---|---|
code_paths | host-selected code | existing individual library/module files |
read_paths | filesystem_read | files or subdirectories |
write_paths | filesystem_write | files or subdirectories |
local_sockets | network_local | exact Unix client socket paths |
process permits children that inherit the policy. network permits
network access; network_local alone does not permit IP traffic.
A permitted service can itself have powerful privileges: do not expose a
Docker socket as if it were a restricted database connection.
The technical baseline includes executable code, Node's loaded libraries, system libraries, path metadata and standard OpenSSL configuration. It does not grant blanket access to the project, home directory or temporary files. Review explicitly granted paths; sandboxing does not prove handler safety.
Payload Constraints
A binding can declare payload constraints applied after the AIR schema and before the handler for input, then before result publication for output.
"payload_constraints": {
"input": {
"request.query": {
"non_empty": true,
"max_length": 120
},
"request.rows": {
"min": 1,
"max": 50
},
"request.mode": {
"allowed_values": ["dry_run", "review", "execute"]
},
"request.recipients": {
"min_items": 1,
"max_items": 5
}
},
"output": {
"$": {
"max_items": 20
}
}
}
Available operators are bounded:
non_emptyandmax_lengthforText;minandmaxforIntorFloat;allowed_valuesfor portable JSON scalars;min_itemsandmax_itemsforList<T>.
A refusal produces ToolPayloadConstraintViolation without displaying the raw payload value.
Run Budgets
The manifest can restrict autonomy budgets:
{
"manifest_version": "touba-manifest-v1",
"run_limits": {
"max_steps": 100,
"max_tool_calls": 20,
"max_agent_invocations": 5,
"max_provider_calls": 4
},
"bindings": {}
}
run_limits concerns the Touba run. timeout_ms and max_payload_bytes inside a binding concern the handler process.
The manifest can restrict an AIR limit. It cannot silently broaden it.
Triggers
A trigger remains inactive until the manifest activates it.
{
"manifest_version": "touba-manifest-v1",
"triggers": {
"trigger:examples.daily_research/DailyResearchSchedule": {
"enabled": true,
"source": {
"kind": "schedule"
},
"limits": {
"max_runs_per_day": 1,
"timeout_ms": 30000
}
}
}
}
The runtime refuses if the event source does not match or if the manifest attempts to broaden a limit declared in AIR.
Relation with the Supply-Chain Lock
The manifest remains the runtime authority: it grants the handler, grants, secrets, memories, limits, and triggers.
A supply-chain lock grants no additional right. It only verifies that AIR, manifest, handlers, SDK metadata, and the declared handler_package identity match expected artifacts. With the dependency artifact extension (SC-2), the same lock can also verify handler package files and explicitly declared dependency artifacts. With the provenance and review extension (SC-3), it can also carry declared provenance and review.
touba supply-chain validate \
--lock touba.lock.json \
--air program.air.json \
--manifest touba.manifest.json
If the manifest changes after lock creation, validation should report drift. The runtime still applies the manifest supplied at execution.
An approved lock review grants no grant, secret, scope, or trigger. It documents a review discipline.
Manifest Boundaries
grantsandsandboxare separate controls.- a required sandbox depends on the mechanism available on the platform.
- The manifest is not a complete permission system.
- No handler is discovered automatically.
- No secret is read implicitly.
- A generated manifest remains a reviewable artifact, not invisible authorization.
- No trigger is activated automatically without an explicit manifest entry.