Core Concepts

Task Chains

A chain is a JSON file that defines how the AI agent behaves — which model to use, what it can do, and how it moves between steps.

Chains are the central building block. The contenox CLI and headless runs all use the same chain engine.

Chains aren't limited to AI loops. A single chain can mix LLM steps, direct tool/tools calls, and manual transitions — in any order. Swapping chains is easy:

# run subcommand — use any chain for this invocation:
contenox run --chain ./my-chain.json "input"
# (falls back to <resolved .contenox>/default-run-chain.json if --chain is omitted)

# chat — set the default session chain:
contenox config set default-chain ./my-chain.json
# (falls back to .contenox/default-chain.json if not set)
{
  "id": "my-chain",
  "tasks": [ ... ],
  "token_limit": 8192
}

Tasks

Each item in tasks[] is a task — a single step with a handler, optional LLM config, and a transition rule.

{
  "id": "ask_model",
  "handler": "chat_completion",
  "system_instruction": "You are a helpful assistant.",
  "execute_config": {
    "model": "qwen2.5:7b",
    "provider": "ollama"
  },
  "transition": {
    "branches": [
      { "operator": "default", "when": "", "goto": "end" }
    ]
  }
}

The handler determines what the task does. See Handlers for all types.

Tools

A tools is a capability the model can call — a local shell command, the local filesystem, or a remote HTTP service.

  • local_shell — run shell commands (requires --shell flag)
  • local_fs — read/write local files
  • Remote tools — any service exposing an OpenAPI v3 spec; by default discovered at <url>/openapi.json, overridable with --spec at registration time
  • MCP servers — any Model Context Protocol server (added via contenox mcp add)

Tools are listed by name in execute_config.tools. Use ["*"] to expose all registered tools, or list them explicitly for least-privilege access:

"execute_config": {
  "tools": ["nws", "local_shell"]
}

Important

"tools": ["*"] grants the model access to every registered tool in this run. For production or sensitive environments, list only the tools the task actually needs. This is how Contenox enforces per-invocation tool policy — the model can only call what you explicitly grant. See Tools reference for access control patterns.

Transitions

After a task runs, the chain evaluates transition branches to decide the next task.

"transition": {
  "branches": [
    { "operator": "equals", "when": "tool-call", "goto": "run_tools" },
    { "operator": "default", "when": "",          "goto": "end" }
  ]
}

Branches are evaluated top to bottom. "goto": "end" terminates the chain.

Data flow

Output from each task is passed as input to the next. Use input_var to read from a specific previous task instead of the immediately preceding one:

{
  "id": "run_tools",
  "handler": "execute_tool_calls",
  "input_var": "ask_model"
}

Macros

Chain JSON supports runtime macros inside string fields:

MacroExpands to
{{var:model}}The active model name from config
{{var:provider}}The active provider from config
{{now:2006-01-02}}Current date (Go time format)
{{toolservice:list}}Comma-separated list of registered tools names

See Transitions & Branching and Handlers for the full reference.