CLI Reference
Project explorer
touba explore [project] [--port <number>] [--no-open]
Opens Architecture, Flow and Governance views in your local browser.
The current project is the default; --port selects a port and
--no-open prints the address without opening a browser. Saved sources
refresh the graph. Ctrl+C closes the service.
See the explorer guide.
Output and diagnostics
--output json flushes the complete envelope before exiting, including pipes and file redirection. The SDK consumes that envelope; invalid JSON remains an error, never a success reconstructed from the trace. Exit codes distinguish success (0), failure (1), waiting (3), stop or rejection (4), and cancellation (5).
Entry errors report missing declared fields and the expected type. Unknown fields are counted without exposing their names, which could contain sensitive data. Binding refusals offer reason-specific guidance rather than describing a supplied manifest as missing. touba serve prints its address on startup unless --quiet is supplied.
The commands on this page assume that the touba command is available in the
terminal.
The Touba VS Code extension helps with editing, diagnostics, and inspection in the editor. It does not replace the CLI for terminal workflows.
Stopping commands and services
On POSIX, when delegating a command such as run, serve or trigger serve,
the CLI forwards SIGTERM, SIGINT and SIGHUP to its direct child process
and waits for it to exit. For both services, sending SIGTERM to the launcher's PID therefore
stops the server and releases its port. Ctrl+C remains available in the
terminal. The child's exit code is preserved; if it terminates by a signal,
the launcher terminates by the same signal.
An operating-system signal is not governed cancellation: it guarantees
neither a complete final trace, a checkpoint, nor reversal of a completed
effect. Use execution controls for governed interruption. SIGKILL cannot
be forwarded; a supervisor forcing termination must manage the entire
process group or tree. Forced termination on Windows is not a POSIX signal
that the CLI can intercept.
Input and resource admission
Keys in --inputs-json must match the selected entry's takes parameters
exactly. Missing or additional parameters, invalid types and unknown record
fields are refused before the first call. Ask responses, human decisions and
agent decisions must reference the current program. Responses supplied in
advance for declared interactions remain valid.
A resource-bindings document may declare required_resources at its root,
alongside resources, for example:
"required_resources": ["memory:app/Records"]
A missing, inactive or unknown required binding is refused before any handler.
A logical memory alone does not require an external backend.
--require-resource-bindings instead requires every resource in the inventory.
Provider identifiers belong to host adapters, not a closed list of databases.
An event_source describes trigger wiring; the adapter must still receive,
authenticate and normalize events. The bindings document does not activate a
trigger in place of the host manifest.
Overview
| Command | Role |
|---|---|
touba init | Initializes a Touba project directory |
touba new module | Creates a .tb source file using the project convention |
touba package | Create, check, archive, install and remove packages |
touba prepare | Prepares or checks derived project artifacts |
touba secret | Manages the development secret store |
touba compile | Compiles .tb source to AIR JSON |
touba run | Executes AIR JSON |
touba serve | Exposes a Touba project to contract clients |
touba deploy | Plans, publishes, activates, or restores an immutable revision |
touba refresh | Asks the project server to re-inspect project artifacts |
touba trigger run | Runs a schedule trigger in a bounded foreground runner |
touba trigger serve | Starts a webhook service for request triggers |
touba inspect | Inspects source, AIR, trace, or manifest artifacts |
touba audit | Validates a trace and can produce an audit export |
touba supply-chain generate | Calculates a lock from actual files; pending review, no overwrite |
touba supply-chain validate | Validates a supply-chain lock for AIR, manifest, handlers, SDK, handler package, declared provenance, and declared review |
touba registry resolve | Resolves and verifies a package version from a static registry |
touba registry check | Checks the catalog, metadata and available files; compares a previous snapshot when supplied |
touba mcp import | Generates Touba contracts from an explicit MCP snapshot |
touba rest scaffold | Generates a Touba tool and bounded HTTP handler from an explicit REST/OpenAPI operation |
touba manifest generate | Generates a binding manifest from AIR |
touba handler stub | Generates handler skeletons for tools |
touba version | Displays the Touba version and build |
touba doctor | Checks the installation and available public surfaces |
touba update | Explains the update policy for the current channel |
touba sdk
touba sdk install javascript
touba sdk install python
touba sdk install python --python python3.12
touba sdk install python --manager uv
touba sdk install python --manager pip
touba sdk path javascript
touba sdk path python
install uses the current directory or --root <project>. Verified archives
are copied into vendor/touba-sdk. JavaScript uses npm offline without install
scripts; Python creates/reuses .venv, never a global environment.
For pnpm/Yarn/Bun projects, use path with that manager instead of creating
a second lockfile. path is read-only and prints the verified absolute path.
A packaged distribution is required; a source checkout does not build SDKs implicitly.
See SDK selection.
touba init
touba init
Initializes the current directory as a Touba project.
The command creates the required local support files without any secret value:
.touba/
.touba/build/
.touba/state/secrets.local.json
.touba/evidence/
touba.project.json
.env
.gitignore
It adds .touba/ and .env to .gitignore.
touba.project.json is versionable. It contains the host language, the project's
Touba SDK, and run profiles:
{
"project_version": "touba-project-v1",
"language": "javascript",
"sdk": "@touba/sdk",
"artifact_layout": "touba-artifacts-v1",
"run_profiles": {
"pure": {
"require_supply_chain_lock": false
},
"dev": {
"require_supply_chain_lock": false
},
"prod": {
"require_supply_chain_lock": true,
"supply_chain_lock": "touba.lock.json"
}
}
}
Choose the host language when creating the project:
touba init --language javascript
# Or, in a different project:
touba init --language python
Then install its SDK with touba sdk install javascript or
touba sdk install python. Python generates .py handlers, contract
tests and a binding to the interpreter in the local .venv.
The CLI refuses unsupported host languages and reports the available options.
To target another directory:
touba init --root my-project
touba new module
touba new module examples.search
Creates a .tb source file using the project convention.
For examples.search, the command creates:
src/examples/search.tb
with:
module examples.search
Useful options:
touba new module examples.search --force
touba new module examples.search --root my-project
--force replaces the file when it already exists.
touba package
new [name] [--org <organization>] [--context] [--yes] creates the author project
in its short-name directory. With no arguments, a questionnaire confirms the
organization.name identity before creation.
check [directory] [--publishing] validates sources, files and requirements
without executing author code.
test [directory] [--env NAME] runs only declared Node tests.
version [patch|minor|major|version] updates the canonical version, without Git.
pack [directory] [--output <archive.tar.gz>] defaults to
dist/<name>-<version>.tar.gz, without overwriting.
add <name|directory|archive.tar.gz> verifies, installs and locks content.
add org.name@1.0.0 --registry <directory|HTTPS-URL> selects an indexed archive.
list validates and lists dependencies; remove <name> removes a dependency
not required by another. With no target in an application, check checks
dependencies; in an author project, it checks the package itself.
checkout <id> --registry <URL> [--root <parent>] retrieves a private draft
into a new author folder.
submit [directory] [--registry <URL>] [--draft <id>] checks and submits an
archive to a private draft. The registry may come from the local link created
by checkout or an earlier submission. Both operations accept --no-browser
and authenticate the terminal; publishing remains a separate action.
submit [directory] --ci <authorization> --registry <URL> prepares a new
draft from an authorized GitHub Actions job. It uses temporary OIDC identity,
id-token: write, and an exact repository/workflow/branch/environment binding.
An authorized member publishes through the interface. The --draft and
--no-browser options are incompatible with this mode.
All accept --json and --root. The root is found from subdirectories.
packages/ is reserved for installed copies. Installation, check and pack
never execute tests or hooks and never grant authority.
See the guide and reference.
touba registry check --registry <source> [--source-root <directory>] checks
index, metadata and optionally archives. --previous <trusted-snapshot>
also checks continuity of previously published identities and versions.
touba prepare
--host-decisions host-decisions.json reads a local JSON file (maximum 64 KiB,
relative to --root). Alternatively, --host-decisions-json '<object>' accepts
the same document inline. Choose one form. The document selects manifest grants, handles,
effects and limits. plan shows the diff, check refuses unapplied changes,
and write applies decisions idempotently. See the
project guide.
touba prepare --mode plan
touba prepare --mode write
touba prepare --mode check
Prepares derived artifacts for a Touba project.
Modes:
| Mode | Role |
|---|---|
plan | shows what would be produced without writing |
write | writes missing artifacts |
check | checks consistency without writing |
A project without an executable tool produces AIR, but no manifest or handler.
A module with pure imports produces prepared AIR where imports of type,
non-sensitive define, and pure function are represented and resolved by
project assembly.
A project with effectful imports can also assemble tool, skill, strategy,
agent, and memory across modules from the same project. References remain
canonical, inter-module callable_by and memory scopes are checked, and tools
produce explicit execution artifacts:
.touba/build/<profile>/air/...
.touba/build/<profile>/touba.manifest.json
.touba/build/<profile>/touba.run-plan.json
.touba/build/<profile>/touba.effective-project.json
handlers/...
touba.secrets.dev.json
touba.secrets.prod.json
A project can also load an explicit package when that package is provided in
touba.project.json or through --package. The package makes its exports
available for imports, but it grants no handler, grant, secret, memory scope,
agent caller, or active trigger.
Common options:
touba prepare --source src/examples/search.tb --mode write
touba prepare --air program.air.json --mode check
touba prepare --package authors/research/touba.package.json --mode write
touba prepare --binding-fragment bindings/search.json --mode write
touba prepare --resource-bindings touba.resources.json --require-resource-bindings --mode check
touba prepare --run-plan touba.run-plan.json --entry strategy:examples.search/Run --mode write
touba prepare --run-plan touba.run-plan.json --mode check
touba prepare --ownership touba.ownership.json --profile prod --mode check
touba prepare --handler-root handlers --handler-command /absolute/path/to/node --mode write
prepare does not start the runtime and does not execute handlers.
The touba-effective-project-v1 projection explains the resolved source, AIR,
entry, handlers, grants, secret handles, scopes, callers, budgets, sandbox,
lock, triggers, and evidence with their provenance. It is derived and never
becomes runtime authority.
--package does not perform global name lookup and does not download anything.
The path points to a local touba-package-v1 manifest.
--binding-fragment reads an explicit touba-binding-fragment-v1 fragment and
composes it into the project manifest. The fragment can propose handler, grants,
secrets, limits, and payload constraints, but it is never consumed directly by
touba run. The assembled manifest remains the runtime authority.
--resource-bindings validates an explicit touba-resource-bindings-v1
artifact against prepared AIR. Resource bindings cover families attachable to
the current AIR: memory_backend, event_source, and decision_provider. The
CLI checks known resources, supported family, grants, required secret handles,
memory scopes, and absence of raw payload. During touba run, the runtime then
passes to the handler only the bindings associated with resources used by the
called tool. The CLI does not select an official backend.
--require-resource-bindings refuses when a logical resource required by AIR has
no active binding.
--run-plan asks prepare to produce or verify an explicit
touba-run-plan-v1 execution plan. The plan points to prepared AIR, the
manifest when a tool is used, the secret profile when a secret is required, and
the supply-chain lock when the profile requires it. It contains no business
inputs, raw prompt, or secret value.
If the entry cannot be inferred unambiguously, specify it:
touba prepare --run-plan touba.run-plan.json \
--entry strategy:examples.search/Run \
--mode write
--ownership asks prepare to validate a touba-ownership-v1 artifact against
prepared AIR and the current profile. Validation covers teams, owners, review
gates, and reviews. It refuses missing reviews, missing owners for sensitive
targets, and fields that attempt to grant runtime authority such as grants,
secrets, handler, provider, callable_by, or automatic-compliance fields.
touba prepare \
--ownership touba.ownership.json \
--profile prod \
--mode check
--require-ownership refuses when no ownership artifact is provided.
touba.ownership.json never modifies the manifest, resource bindings, run plan,
locks, secrets, handlers, or memory scopes.
Canonical project layout
Projects declare artifact_layout: "touba-artifacts-v1". There is one layout:
.touba/build/<profile> for prepared artifacts and .touba/state for runtime
state. Older layouts are refused without rewriting user files. Prepare and
project runs default to dev. A unique entry is inferred; otherwise set
entry in the project configuration or pass --entry to prepare.
touba secret
touba secret set OPENAI_API_KEY --value-stdin
touba secret list
touba secret check OPENAI_API_KEY
touba secret remove OPENAI_API_KEY
Manages a development secret store.
The command displays handles, not values.
Example:
printf '%s' "$OPENAI_API_KEY" | touba secret set OPENAI_API_KEY --value-stdin
touba secret check OPENAI_API_KEY
To target a project:
touba secret list --root my-project
The runtime reads this store only when an explicit secrets file requests it with
a touba_store source.
touba compile
touba compile source.tb --out program.air.json
Compiles .tb source to AIR JSON.
Inside a project, the command finds the project root from the source file and
resolves installed-package imports after checking their integrity, even when
the terminal is open elsewhere. touba prepare also prepares manifests,
bindings and execution plans for the whole project.
--out is the recommended mode: Touba verifies that the target ends with
.air.json and that compiler output is an AIR JSON document before writing the
file.
Shell redirection remains possible for advanced uses:
touba compile source.tb --stdout > program.air.json
In this case, --stdout makes the pipeline explicit. The shell still creates the
file to the right of >; Touba cannot validate its extension. Without --out or
--stdout, touba compile refuses execution.
The Touba runtime executes AIR, not the .tb file directly.
touba run
For local diagnostics, --handler-diagnostics <new-file> requires a POSIX
dev run plan without hardened profile or required lock. See the
private handler channel.
touba run program.air.json
Executes AIR JSON.
Traces are stored in the project's .touba/traces.sqlite by default.
--trace-store <database.sqlite> selects another private SQLite journal.
--trace-out <trace.json> exports the JSON document. See
trace storage.
--output json-reference returns the result with a journal reference.
touba trace read --store <database.sqlite> --reference-json <json> --limit 100
then reads events in pages. See paged reads.
touba trace archive --store <database.sqlite> previews retention.
Add --destination <new-archive.sqlite> --apply to archive successful runs
and remove them from the source after verifying the copy. For a project
server, archive its complete state with the server stopped.
--trace-pure-functions full|calls selects pure-function trace detail.
full is the default; calls keeps calls, results and failures, together
with all governance events. The option is also available with touba serve.
See trace detail.
With an explicit run plan:
touba run --run-plan touba.run-plan.json
From an explicit project entry:
touba run --project . --entry strategy:examples.search/Run --profile dev
The facade resolves .touba/build/dev/touba.run-plan.json, verifies the entry,
and passes that explicit plan to the low-level runner. The runtime does not
discover authority artifacts by filename.
The run plan replaces repeated artifact options, not business inputs. It can point to:
{
"run_plan_schema_version": "touba-run-plan-v1",
"entry_ref": "strategy:examples.search/Run",
"air": "air/examples/search.air.json",
"manifest": "touba.manifest.json",
"secrets_profile": "touba.secrets.dev.json",
"profile": "dev",
"outputs": {
"mode": "show"
}
}
The runtime refuses before execution when AIR is missing, entry_ref does not
exist, AIR requires a manifest or secret profile that is missing, a strict
profile requires a missing lock, the supply-chain lock has drifted, or the run
plan contains sensitive fields such as inputs, payload, prompt, secret,
or secrets.
If --manifest points to a touba-binding-fragment-v1 fragment instead of an
assembled touba-manifest-v1 manifest, the runtime refuses with
BindingFragmentNotAssembled.
Inputs remain supplied separately:
touba run --run-plan touba.run-plan.json \
--inputs-json '{"request":{"topic":"demo"}}'
Explicit resource bindings:
touba run program.air.json \
--resource-bindings touba.resources.json \
--require-resource-bindings
The runner validates the artifact before dispatch, but it does not create a PostgreSQL, HTTP, queue, Vault, or control-surface connection.
With explicit inputs:
touba run program.air.json \
--inputs-json '{"request":{"topic":"demo"}}'
With manifest:
touba run program.air.json \
--manifest touba.manifest.json \
--inputs-json '{"request":{"topic":"demo"}}'
With secrets:
touba run program.air.json \
--manifest touba.manifest.json \
--secrets touba.secrets.dev.json
With a supply-chain lock:
touba run program.air.json \
--manifest touba.manifest.json \
--supply-chain-lock touba.lock.json \
--require-supply-chain-lock
--supply-chain-lock asks touba run to validate the lock before dispatch.
--require-supply-chain-lock makes this gate strict: missing lock, supply-chain
error, or supply-chain warning refuses execution before a handler starts.
Without --require-supply-chain-lock, a supply-chain warning remains
non-blocking. The lock grants no authority, reads no secrets, and does not prove
that the handler is safe. The manifest remains the runtime authority for
handlers, grants, secrets, memories, limits, and triggers.
With a project profile:
touba run program.air.json \
--profile prod \
--manifest touba.manifest.json
--profile prod reads touba.project.json in the current directory and applies
the prod profile. By default, this profile requires touba.lock.json and
enables the strict supply-chain gate before dispatch. --profile dev keeps the
current behavior without a mandatory lock.
With ask inputs supplied by file:
touba run program.air.json \
--user-inputs user-inputs.json
With explicit terminal input for a manual trial:
touba run program.air.json \
--interactive-user-inputs
--interactive-user-inputs cannot be combined with --user-inputs or
--user-inputs-json.
With human decisions supplied at startup:
touba run program.air.json \
--human-decisions human-decisions.json
To suspend a run at a human decision and resume without replaying effects that already occurred:
touba run program.air.json \
--human-checkpoint-out human.checkpoint.json \
--output trace
touba run program.air.json \
--human-resume-checkpoint human.checkpoint.json \
--human-decisions-json '{"approval:example":"approved"}' \
--output trace
The checkpoint covers human_approval nodes and request_human_review
requests attached to the execution graph. Ambiguous resume attempts are
refused. For asynchronous client interactions, touba serve stores
the checkpoint and resumes the run from the authenticated decision.
With explicit autonomy budgets:
touba run program.air.json \
--max-run-ms 30000 \
--max-steps 100 \
--max-tool-calls 20 \
--max-agent-invocations 5 \
--output trace
With JSON autonomy budgets:
touba run program.air.json \
--run-limits-json '{"max_steps":100,"max_tool_calls":20}' \
--output trace
--run-timeout-ms produces a cancelled outcome. --max-run-ms produces a
budget refusal with failure status.
With an explicit trigger event:
touba run program.air.json \
--manifest touba.manifest.json \
--trigger-event-json '{"trigger_ref":"trigger:examples.daily/DailyRun","event_id":"evt-001","source_kind":"schedule"}' \
--output trace
The manifest must enable the trigger. The runtime refuses before execution if the trigger does not exist in AIR, the manifest entry is missing or inactive, the event source does not match, or the manifest attempts to widen limits declared in AIR.
With an event file:
touba run program.air.json \
--manifest touba.manifest.json \
--trigger-event trigger-event.json \
--output trace
With dry run:
touba run program.air.json \
--manifest touba.manifest.json \
--trigger-event trigger-event.json \
--trigger-dry-run
Dry run displays checks without starting the trigger target. It validates the alignment between AIR, manifest, event source, and limits.
With the foreground runner:
touba trigger run program.air.json \
--manifest touba.manifest.json \
--trigger trigger:examples.daily/DailyRun \
--max-runs 1 \
--state touba.triggers.sqlite \
--trace-out trace.json
The runner waits for a real interval declared in source with one of these formats:
every <n>s
every <n>m
every <n>h
It then generates a normalized trigger event without raw payload and calls the
same runtime as --trigger-event-json. --max-runs and --state are required
for the foreground runner.
--state <touba.triggers.sqlite> activates durable trigger state
touba-trigger-state-v1. The runner stores consumed event_id values,
acceptances, refusals, and the UTC day key used to apply max_runs_per_day. A
previously consumed event_id for the same trigger_ref is refused with
TriggerReplayRejected before the strategy is started again. An acceptance
recorded on a previous day does not block the first event of the current day.
This file contains no raw payload and grants no runtime authority. The path
passed to --state must end with .triggers.sqlite.
With the webhook service:
touba trigger serve program.air.json \
--manifest touba.manifest.json \
--state touba.triggers.sqlite \
--queue touba.trigger-queue.sqlite \
--host 127.0.0.1 \
--port 8787 \
--trace-dir traces \
--max-attempts 3 \
--signature-secret-env TOUBA_TRIGGER_SIGNATURE_SECRET
The service routes request triggers activated by the manifest. Each accepted
request is appended to the touba-trigger-queue-v1 queue, then passed to the
same runtime as --trigger-event-json. The queue stores event identity, method,
path, payload size, and SHA-256 digest; it does not store the raw body. When the
manifest declares payload, only JSON fields referenced by payload.map become
persisted strategy arguments. The runtime revalidates those arguments against
the target signature. --state and --queue must point to paths ending in
.triggers.sqlite and .trigger-queue.sqlite.
Main options:
| Option | Role |
|---|---|
--trigger <trigger_ref> | restricts the service to one request trigger |
--trace-dir <dir> | writes one JSON trace per processed entry |
--max-events <n> | stops the service after n processed entries |
--max-attempts <n> | bounds retries for non-structural failures |
--processing-timeout-ms <n> | requeues a stale processing entry |
--auth-token-env <NAME> | requires a bearer token or x-touba-trigger-token |
--signature-secret-env <NAME> | requires x-touba-signature: sha256=<hex> |
--secrets <path> | resolves declared secret handles for triggered runs |
Source and manifest for a typed webhook:
module examples.webhook
strategy RunWebhook
takes message as Text
gives Text
do
give message
trigger WebhookRun
on request POST "/webhook/run"
runs strategy RunWebhook
with message as payload.message
limits
max_runs_per_day as 100
timeout_ms as 30000
{
"manifest_version": "touba-manifest-v1",
"bindings": {},
"triggers": {
"trigger:examples.webhook/WebhookRun": {
"enabled": true,
"source": { "kind": "request" },
"payload": {
"format": "json",
"content_types": ["application/json"],
"max_bytes": 4096,
"map": {
"message": "$.message"
}
},
"limits": {
"max_runs_per_day": 100,
"timeout_ms": 30000
}
}
}
}
Touba provides an explicit daemon for request -> strategy. Distributed
schedulers, distributed queues, cloud adapters, system supervision, and complete
durable multi-process recovery remain separate layers.
With run controls:
touba run program.air.json \
--cancel-before-dispatch \
--output trace
touba run program.air.json \
--cancel-on-pause \
--output trace
touba run program.air.json \
--run-timeout-ms 5000 \
--output trace
touba run program.air.json \
--manifest touba.manifest.json \
--trigger-event-json '{"trigger_ref":"trigger:examples.daily/DailyRun","event_id":"evt-001","source_kind":"schedule"}' \
--kill-switch-enabled \
--output trace
These options produce cancel, timeout, or kill-switch traces. They do not provide a system hard kill or distributed control plane.
With an explicit AIR entry:
touba run program.air.json \
--entry skill:examples.project/RunGreeting
--entry expects an AIR reference that exists in the compiled program. Without
--entry, the runtime chooses the default entry of the current AIR.
With an explicit agent decision:
touba run program.air.json \
--agent-decisions-json '{"agent:examples.research/Researcher":{"target_ref":"skill:examples.research/BuildBrief","reason":"brief requested"}}'
The decision must select a capability declared in uses for that agent. If the
requested reference is not authorized, the runtime refuses before entering the
capability.
With an agentic decision provider:
touba run program.air.json \
--agent-decision-provider providers/researcher.provider.mjs \
--agent-decision-provider-content-mode opaque_refs \
--agent-decision-provider-initial-mode capabilities \
--agent-decision-provider-timeout-ms 30000 \
--agent-decision-provider-max-retries 1 \
--max-agent-steps 8 \
--max-provider-calls 4
The provider module exports decideAgentCapability, decide, or a default
function. The runtime calls it with the touba-agent-decision-v1 protocol. The
request also contains model_input.protocol = "touba-agent-model-input-v1": a
structured model input that separates agent responsibility, instructions, user
data, external content, and progressive capability disclosure.
--agent-decision-provider-content-mode accepts inline or opaque_refs.
The default mode is inline. In opaque_refs mode, external observations and
runtime inputs that are not explicit user intent are replaced with opaque
references and metadata; their raw payload is not included in the provider
request.
--agent-decision-provider-initial-mode accepts summary or capabilities.
The default mode is summary. capabilities presents the authorized catalog in
the first provider request; it is recommended when the host already knows that
the agent must choose among declared capabilities and wants fewer model
roundtrips. In both modes, the runtime still verifies uses, callable_by,
arguments, budgets, and manifest constraints before execution. Every capability
exposed to a decision provider through agent.uses must declare an explicit
source description; otherwise the runtime refuses before the provider call
with AgentCapabilityDescriptionRequired.
The module can export non-secret metadata. These metadata are included in traces to identify the provider, model, or prompt template without exposing raw payload.
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",
};
The provider can answer directly or ask for the full catalog:
import { isDeepStrictEqual } from "node:util";
export function decideAgentCapability(request) {
const target = "skill:examples.research/BuildBrief";
const input = request.inputs.request;
const completed = request.observations?.findLast((item) =>
item.target_ref === target
&& isDeepStrictEqual(item.arguments, { request: input })
&& typeof item.value?.summary === "string");
if (completed) return {
action: "answer_directly", source: "custom_provider",
reason: "The requested dataset brief is available in the matching observation.",
result: completed.value.summary,
};
if (request.mode === "finalization") return {
action: "cannot_complete", source: "custom_provider",
reason: "No matching brief is available within the execution budget.",
};
if (request.mode === "summary") {
if (input?.query === "hello") return {
action: "answer_directly", source: "custom_provider",
reason: "A greeting needs no dataset operation.", result: "Hello.",
};
return { action: "request_capabilities", source: "custom_provider",
reason: "The requested brief still requires execution." };
}
if (!request.capability_refs.includes(target)) throw new Error("Brief capability unavailable");
return { target_ref: target, source: "custom_provider",
reason: "The authorized skill produces the requested dataset brief.",
arguments: { request: input } };
}
In catalog mode, it can also request governed human review:
return {
action: "request_human_review",
target_ref: "human_review",
source: "custom_provider",
reason: "The result must be confirmed before continuing",
review_prompt: "Validate this intermediate result.",
};
The runtime then verifies target_ref against uses, maps arguments to the
capability signature, and refuses before execution when the target or arguments
are invalid.
--max-agent-steps bounds the sequential loop of a provider-driven agent.
--max-provider-calls bounds the number of provider calls. When a limit is
exceeded, the run fails with an observable refusal instead of continuing
indefinitely.
A provider can call an external model. In JavaScript, @touba/sdk provides
createAiSdkDecisionProvider and createOpenAiDecisionProvider. No LLM vendor
becomes the official authority of Touba: the provider is configured explicitly,
then the runtime revalidates.
touba run Outputs
touba run program.air.json --output show
touba run program.air.json --output result
touba run program.air.json --output trace
touba run program.air.json --output all
touba run program.air.json --output run-summary
Integration output contract
Use touba run program.air.json --output json: the touba-run-result-v1
envelope contains status, reason, result, messages, and trace.
Pending questions appear in pending_interactions, an array of
{interaction_ref, prompt} objects. For user_input_pending,
pending_interaction also points to the first question. The array may also
appear in a mixed human-approval pause. Branches that have not started are not
listed. Answer by occurrence reference, then resume with the saved checkpoint.
Business messages remain separate from traces; private checkpoints are excluded.
Do not parse human-readable output.
| Exit code | Meaning |
|---|---|
| 0 | Success |
| 1 | Admission or execution failure |
| 2 | Invalid CLI options |
| 3 | Waiting for human approval or user input |
| 4 | Explicit stop, rejected or expired approval |
| 5 | Cancellation, including timeout or human cancellation |
reason distinguishes completed, explicit_stop, human_approval_pending,
user_input_pending, human_approval_rejected, human_approval_expired,
human_approval_cancelled, cancelled, timeout, and kill_switch.
Runtime failures expose their machine error code. Scripts must handle exit 3
as waiting, not success.
touba inspect trace.json shows a compact chronology and observed limits;
--json retains the complete chronology. A supplied explanation appears as
reported_reason; the inspector never invents model intent.
Modes:
| Mode | Role |
|---|---|
show | displays only show messages; default mode |
result | displays the returned value |
trace | displays the complete JSON trace |
all | displays show, result, and trace sections |
run-summary | displays touba-run-summary-v1, a stable JSON summary for integrations and observation scripts |
To keep a trace in a file while preserving user output:
touba run program.air.json \
--trace-out trace.json
touba serve
The project server API guide covers interaction routes, decision identity, approval context, resume and providers.
touba serve --project-root my-project --port 8791
Starts the Touba project server. This command provides a real-time surface for clients that consume Touba public contracts. It exposes the inspected project state, the authority graph, product identity, run summaries, human approvals, server events, and reviewable change proposals.
The server refuses ambiguous startup configurations: invalid ports, missing
contract roots, inconsistent decision-store paths, or network exposure without
an explicit token. By default, it listens on 127.0.0.1.
TOUBA_PROJECT_TOKEN=replace-with-a-strong-token \
TOUBA_IDENTITY_SERVICE_TOKEN=replace-with-a-strong-service-token \
touba serve \
--project-root my-project \
--host 127.0.0.1 \
--port 8791 \
--auth-token-env TOUBA_PROJECT_TOKEN \
--identity-control-plane-url https://identity.example.com \
--identity-service-token-env TOUBA_IDENTITY_SERVICE_TOKEN
When --auth-token-env is configured, clients send
Authorization: Bearer <token> on HTTP requests and on the /events stream.
With the control plane, clients also send
X-Touba-Identity-Token; the server verifies the active session and required
permission for each route.
The public routes are governed by the product-surfaces schemas:
| Route | Contract |
|---|---|
GET /state | live project, run, trigger, and decision state |
GET /events | touba-project-event-stream-v1, carrying touba-project-event-v1 envelopes |
GET /authority/graph | touba-authority-graph-v1, covering agents, skills, tools, strategies, human gates, and grants |
GET /identity | touba-product-identity-v1, covering users, teams, devices, sessions, assignments, and escalation policies |
POST /project/refresh | touba-project-refresh-request-v1 to touba-project-refresh-v1 |
POST /runs/sandbox | governed execution of a declared entry point |
POST /triggers/fire | manual manifest-governed trigger |
POST /elements/propose | semantic creation of a Touba primitive |
POST /governance/relations/propose | semantic authority-relation change |
POST /changes/propose | touba-project-change-proposal-v1 to touba-project-change-proposed-v1 |
POST /changes/apply | touba-project-change-apply-v1 to touba-project-change-result-v1 |
GET /deployments | revisions and current activation |
POST /deployments/plan | deployment checks and plan |
POST /deployments/publish | immutable revision publication |
POST /deployments/activate | verified revision activation |
POST /deployments/rollback | restore the preceding revision |
Each event contains an event_id, a monotonic sequence for the current
server process, a type, source, emitted_at, and a versioned payload.
Clients can display or replay observable changes without parsing free-form
text.
The authority graph is derived from Touba artifacts. An inconsistent reference is exposed as a diagnostic, never converted into implicit authority. Product identity identifies the humans and devices used by a client; it does not replace Touba Engine runtime checks.
A change proposal does not write to the project directly. The server validates
paths, JSON contracts and .tb compilation, then returns a proposal that can be
applied or refused. An accepted application writes the complete change as one
transaction; an error restores the initial state.
By default, touba serve loads touba.secrets.dev.json when that file exists
at the project root. --secrets <file> selects another profile. Resolved values
remain inside the server and runtime; clients never receive them.
The complete flow is described in the project server API guide.
touba deploy
touba deploy plan --root . --profile prod --target https://deploy.example.com
The plan creates a deterministic bundle and checks sources, manifests, digests, the supply-chain lock, handlers and source-revision state.
export TOUBA_DEPLOY_TOKEN='replace-with-a-strong-token'
touba deploy publish \
--root . \
--profile prod \
--target https://deploy.example.com \
--auth-token-env TOUBA_DEPLOY_TOKEN
Publication adds an immutable revision. Activation remains explicit:
touba deploy list \
--target https://deploy.example.com \
--auth-token-env TOUBA_DEPLOY_TOKEN
touba deploy activate \
--target https://deploy.example.com \
--auth-token-env TOUBA_DEPLOY_TOKEN \
--revision sha256:...
touba deploy rollback \
--target https://deploy.example.com \
--auth-token-env TOUBA_DEPLOY_TOKEN
Start a target:
touba deploy target serve \
--storage /srv/touba/revisions \
--auth-token-env TOUBA_DEPLOY_TOKEN \
--host 127.0.0.1 \
--port 8792
A non-loopback target requires --tls-cert and --tls-key. Tokens stay in the
CLI or project server and never enter contracts sent to clients.
touba refresh
touba refresh --url http://127.0.0.1:8791
Asks an already running project server to re-inspect Touba artifacts. The response reports observed files, changes detected since the server's previous snapshot, and project readiness diagnostics. A client uses the same route to stay synchronized with changes made from an editor or through the CLI.
touba inspect
touba inspect program.air.json
touba inspect trace.json
touba inspect touba.manifest.json
touba inspect touba.package.json
touba inspect touba.resources.json
touba inspect touba.run-plan.json
touba inspect .touba/build/dev/touba.effective-project.json
touba inspect .touba/build/dev/touba.effective-project.json --json
touba inspect touba.ownership.json
touba trigger state touba.triggers.sqlite --trigger trigger:examples.daily_research/DailyResearchSchedule
touba inspect trace-audit.export.json
touba inspect --supply-chain touba.lock.json
touba inspect --supply-chain supply-chain.report.json
touba inspect program.air.json --report-out program.inspect.txt
touba inspect trace.json --otel-out trace.otel.json
Inspects a Touba artifact without inventing missing data.
Depending on the file provided, the command can display:
- AIR declarations;
- execution graphs;
- traces;
- memory provenance and integrity counters observed in traces;
- manifest bindings;
- local packages, binding fragments, resource bindings, and run plans provided explicitly;
Availability graph, showing modules, imports, declarations, and available exports;Authority graph, showing AIR requirements, manifest, resource bindings, run plan, and supplied lock;OwnershipandResponsibility graph, showing teams, owners, review gates, and reviews without runtime authority;- durable trigger states, including acceptances, refusals, and consumed
event_idvalues; - audit manifests, reports, and exports;
- supply-chain locks and reports;
- useful missing data.
touba inspect does not read handlers, memory backends, .env files, secret
files, or local stores. It does not scan the workspace to discover a neighboring
package or manifest.
For touba-effective-project-v1, text output and --json use the same
deterministic document. The absent, non_applicable, derived, declared,
and effective states are preserved. The projection contains no secret value,
business payload, prompt, result, or memory content.
With --report-out <report.inspect.txt>, the command writes the same text
report to a file with an explicit .inspect.txt suffix and keeps standard
terminal output.
With --otel-out <trace.otel.json>, the command writes an OpenTelemetry JSON
projection of a native trace. The option requires either a single trace file or
--trace <trace.json> in a multi-artifact inspection.
The projection maps events to GenAI spans such as invoke_workflow,
invoke_agent, or execute_tool when possible, and exports only references,
counters, codes, and non-sensitive metadata.
Explicit multi-artifact inspection:
touba inspect \
--air build/touba/project.air.json \
--manifest build/touba/touba.manifest.json \
--package authors/research/touba.package.json \
--resource-bindings touba.resources.json \
--run-plan touba.run-plan.json \
--ownership touba.ownership.json
The touba-binding-fragment-v1 fragment can also be inspected with
--binding-fragment, but it is displayed as non-authoritative for runtime. Only
the assembled manifest is an execution authority.
With --source, inspection compares artifact references to the supplied file.
On Windows, D:\project\main.tb and d:\project\main.tb name the same drive.
The comparison preserves folder and filename case, as well as the original
references; it does not modify the artifacts.
touba audit
touba audit --trace trace.json
Validates a Touba trace and produces a trace-audit-validation-v1 report.
With more context:
touba audit \
--trace trace.json \
--air program.air.json \
--source source.tb \
--manifest touba.manifest.json
With export:
touba audit \
--trace trace.json \
--air program.air.json \
--source source.tb \
--manifest touba.manifest.json \
--retention-class project_audit \
--redaction-policy no_secrets_no_raw_prompts_no_memory_content \
--export trace-audit.export.json \
--report-out trace-audit.trace-audit-report.json
Options:
| Option | Role |
|---|---|
--trace | trace to validate, required |
--air | associated AIR, optional |
--source | explicit .tb source; repeat for imported modules |
--manifest | associated runtime manifest, optional |
--audit-manifest | existing audit manifest to verify |
--retention-class | declarative retention class |
--redaction-policy | expected redaction policy |
--export | export file, written only when the report is ok |
--report-out | trace-audit-validation-v1 report file written with .trace-audit-report.json suffix |
--output text|json | report format |
touba audit does not sign artifacts, create a legal timestamp, or declare
regulatory compliance.
touba supply-chain generate
Calculates a pending-review lock without overwriting an existing lock or
executing handlers. Static local JavaScript and Python imports are inventoried
alongside package.json or pyproject.toml identity.
touba supply-chain generate --air program.air.json \
--manifest touba.manifest.json --out touba.lock.json
Additional options: repeatable --air, --package-root, repeatable --file,
--entrypoint-arg <index|command>, --sdk-metadata-json,
--python <trusted-interpreter> (isolated Python 3.11+ analysis).
Declared dependencies require their manager's lockfile. Artifact bytes are
checked, not dependency resolution or the installed environment.
See the supply-chain guide.
touba supply-chain validate
touba supply-chain validate \
--lock touba.lock.json \
--air program.air.json \
--manifest touba.manifest.json \
--require-review \
--report-out project.supply-chain-report.json
Validates a supply-chain lock against explicitly supplied artifacts.
Validation covers:
sha256digest of AIR;sha256digest of the manifest;sha256digest of listed handlers;- handler command,
cwd, andargs; - declarative SDK metadata, including name, version, and expected handler protocol;
- declared
handler_packageidentity for handlers; - handler package files and declared dependency artifacts under
handler_package; - declared lock provenance;
- declared lock review and associated evidence;
- anti-leak diagnostics on authority fields.
Options:
| Option | Role |
|---|---|
--lock | touba-lock-v1 lock, required |
--air | AIR expected by the lock, required |
--manifest | manifest expected by the lock, required when the lock declares one |
--report-out | touba-supply-chain-validation-v1 report file written with .supply-chain-report.json suffix |
--output text|json | report format |
--strict | also fails on warnings |
--require-review | requires a consistent approved review in the lock |
JSON example:
touba supply-chain validate \
--lock touba.lock.json \
--air program.air.json \
--manifest touba.manifest.json \
--output json
Example with mandatory review:
touba supply-chain validate \
--lock touba.lock.json \
--air program.air.json \
--manifest touba.manifest.json \
--require-review
touba supply-chain validate does not execute handlers, scan the workspace, read
secrets, sign artifacts, verify a registry, or perform vulnerability auditing.
handler_package is a declared identity and declared artifact root, not a trust
source. An approved review is a declared discipline, not a signature,
compliance proof, or Verified / Unverified status.
touba registry resolve
This inspection command selects an exact entry from an explicitly chosen local
or HTTPS registry. It checks index and metadata digests, version, protocol
compatibility and review status. With --source-root it also checks local
artifact digests. The package reference uses pkg:<qualified.name>.
touba registry resolve --registry ./registry --package pkg:acme.review \
--version 0.1.0 --source-root ./registry --json
This assumes that your registry contains that package. There is no default
registry or preinstalled example package. Use --out <file.json> only when you
want to save the inspection record (touba-static-registry-lock-v1).
Draft and deprecated records require --allow-draft and --allow-deprecated
respectively; yanked entries are refused. registry check can audit all metadata,
including yanked entries. Neither command grants runtime authority.
For installation use touba package add, which also checks the archive, source
contracts, compatibility and exact dependency closure, then records the
installation lock. The optional registry inspection record does not replace it.
touba mcp import
touba mcp import mcp.demo.json \
--module integrations.mcp.demo \
--out integrations/demo \
--mode write
Generates reviewable Touba artifacts from an explicit MCP tools snapshot:
.tb source, manifest fragment, MCP bridge config, bridge handlers, secrets
template, import report, and local README.
The input file uses touba-mcp-import-config-v1:
{
"mcp_import_config_version": "touba-mcp-import-config-v1",
"server": {
"name": "demo",
"transport": "snapshot",
"secret_handles": ["DEMO_MCP_TOKEN"],
"timeout_ms": 5000,
"max_payload_bytes": 65536
},
"tools": [
{
"name": "search",
"description": "Search a governed MCP source",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
},
"outputSchema": {
"type": "object",
"properties": {
"summary": { "type": "string" }
},
"required": ["summary"]
}
}
]
}
Common options:
| Option | Role |
|---|---|
--module <module.name> | Touba module that receives the generated types and tools |
--out <dir> | output directory under the project root |
--mode plan|write|check | previews, writes, or checks generated files |
--select <tool> | imports only one named MCP tool, repeatable |
--force | allows overwriting a generated file that differs |
--json | prints the import report as JSON |
The generated mcp.bridge.config.json configures the approved MCP stdio
server that will execute tools/call:
{
"mcp_bridge_config_version": "touba-mcp-bridge-config-v1",
"server": {
"transport": "stdio",
"command": "/path/to/mcp-server",
"args": [],
"timeout_ms": 5000,
"max_payload_bytes": 65536,
"max_text_content_length": 65536,
"env": {
"SERVICE_TOKEN": {
"from_secret_handle": "DEMO_MCP_TOKEN"
}
}
}
}
env maps variables expected by the MCP server to secret handles already
granted to the tool. The file remains versionable because it contains no secret
value.
The report separates imported tools from refused tools. Refusals cover
unmappable schemas, missing selections, invalid secret handles, and drift
detected by --mode check.
The generated bridge handler initializes an MCP stdio session, calls
tools/call, normalizes structuredContent or bounded text content, and
returns controlled errors through the Touba handler protocol. Effective
authority remains in the manifest, secrets, approvals, and Touba runtime
policies.
touba rest scaffold
touba rest scaffold rest.search.json \
--module integrations.rest.search \
--out integrations/search \
--mode write
Generates integration artifacts for an explicit HTTP operation: .tb source,
manifest fragment, REST handler configuration, minimal HTTP handler, secrets
template, generation report, and local README.
The input file uses touba-rest-scaffold-config-v1:
{
"rest_scaffold_config_version": "touba-rest-scaffold-config-v1",
"service": {
"name": "search",
"base_url": "https://api.example.test",
"secret_handles": ["SEARCH_API_KEY"],
"timeout_ms": 5000,
"max_payload_bytes": 65536
},
"operation": {
"name": "search_web",
"method": "GET",
"path": "/v1/search",
"description": "Search a governed API",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" },
"max_results": { "type": "integer" }
},
"required": ["query"]
},
"outputSchema": {
"type": "object",
"properties": {
"summary": { "type": "string" },
"source_count": { "type": "integer" }
},
"required": ["summary"]
}
}
}
The same format can target a simple OpenAPI specification with openapi and
operation_id. The scaffold extracts the named operation, its parameters, its
JSON body, and its response schema.
Common options:
| Option | Role |
|---|---|
--module <module.name> | Touba module that receives the generated types and tool |
--out <dir> | output directory under the project root |
--mode plan|write|check | previews, writes, or checks generated files |
--force | allows overwriting a generated file that differs |
--json | prints the generation report as JSON |
The generated rest.handler.config.json describes the base URL, operation,
timeouts, payload limits, and secret mapping. The manifest fragment declares
network and secret_read when handles are requested, but it does not grant
silent authority to the project.
The report separates generated operations from refusals. Refusals cover JSON
schemas that cannot be mapped to Touba types, missing OpenAPI operations, and
drift detected by --mode check.
touba manifest generate
touba manifest generate program.air.json --out touba.manifest.json
Generates a binding manifest from tools declared in AIR.
Common options:
touba manifest generate program.air.json \
--out touba.manifest.json \
--handler-command /absolute/path/to/node \
--handler-root handlers
The generated manifest is a starting point. It must be reviewed before running a program with tools.
The manifest can also carry payload constraints, for example:
{
"bindings": {
"tool:examples.fetch_source/FetchSource": {
"payload_constraints": {
"input": {
"request.query": {
"non_empty": true,
"max_length": 120
},
"request.mode": {
"allowed_values": ["dry_run", "review", "execute"]
},
"request.recipients": {
"min_items": 1,
"max_items": 5
}
}
}
}
}
}
These constraints are evaluated by touba run after the AIR schema and before
the handler. A refusal produces ToolPayloadConstraintViolation without
displaying the refused raw value.
Base constraints cover non_empty, max_length, min, and max. The
allowed-values extension adds allowed_values to bound a field to an explicit
list of scalar JSON values (Text, Boolean, Int, Float). Touba does not
treat these constraints as expressions, regexes, or a policy language. List
cardinality constraints add min_items and max_items on values already
validated as List<T> by AIR.
touba handler stub
touba handler stub program.air.json
Generates handler skeletons for tools declared in AIR.
Common options:
touba handler stub program.air.json \
--handler-root handlers
To generate only one tool:
touba handler stub program.air.json \
--tool-ref tool:examples.search/SearchDatasets \
--handler-root handlers
The generated stub does not implement the external effect. It lays down the handler contract to complete.
touba version
touba version
Displays two lines: touba <version> and build <short identifier>.
The identifier is the first 12 characters of the assembled toolchain payload's
SHA-256 fingerprint. It distinguishes development builds without introducing
another version number.
Use touba doctor to check the installation.
An unpackaged source checkout reports source-local. An installation without
a recognized assembly identity reports unknown: rebuild and reinstall the
toolchain to obtain this identity. The identifier depends on neither the
installation directory nor environment variables. It identifies the content
at assembly time; it is neither a signature nor a fresh integrity check on
each invocation.
touba doctor
touba doctor
Checks the active installation: Node version, Touba component versions, presence of public commands, and project profiles available in the current directory. The report identifies warnings and errors without reading secret values.
touba update
touba update
touba update --json
Explains the update policy for the current channel.
The command reports the installed version, channel, platform, Touba Hub URL,
expected archive and reinstall commands. --json returns the same contract in
a machine-readable form.
Updates use explicit reinstallation from a new archive or from the package manager channel that installed Touba.
Parallel runs
touba run accepts --parallel-checkpoint-out <path>,
--parallel-resume-checkpoint <path> and --parallel-limits-json <object>.
Private checkpoints are atomically written with mode 0600 before dispatch,
after results and before join. Supply --human-decisions-json for the exact
pending occurrence's approval_ref; one decision cannot release a sibling.
Host ceilings are maxBranches (1024), maxExternalCalls (16),
maxDepth (64), maxConcurrency and maxItems (1024 each),
maxJournalEntries (100000) and maxCheckpointBytes (16777216).
Host ceilings may tighten source limits. Resume cannot enlarge saved ceilings.
Keep the effect journal alongside checkpoints for writing tools. An uncertain
external outcome without journal evidence is refused, never blindly repeated.
The checkpoint covers the group before join, not arbitrary workflow execution
after that join. See the tutorial.
Trusted human approval adapter
touba run and touba serve accept
--human-approval-host <host.mjs|host.py|pkg:organization.name/host-id>.
Python hosts export attest_human_approval and optionally initiator_ref.
The selected package is checked before loading.
--human-approval-authority-timeout-ms sets the technical attestation timeout
from 1 to 60,000 ms (default: 5,000). A timeout refuses the decision and leaves
the program's business deadline unchanged.
The module exports attestHumanApproval and optionally initiatorRef.
Constrained decisions include an opaque evidence_ref, not client-supplied
roles. See the executable tutorial.
An expired source deadline can be resumed without a decision; use a separate
--human-checkpoint-out path to retain a new escalation wait.