App Composition
Three ways to combine Digitorn apps. Each serves a different shape of workflow.
| Pattern | Mechanism | When to use |
|---|---|---|
call_app tool | One agent calls another deployed app as a tool, in-flight. | Ad-hoc composition; agent decides at runtime which apps to invoke. |
flow: graph | In-app workflow (agents, tools, IF, parallel). Prefer this for linear/branching automation. | Background or conversation apps that need deterministic routing. |
| Multi-agent | One app declares a coordinator + specialists in agents:. | Cohesive team behind one app; specialists share workspace + memory with the coordinator. |
runtime.mode: pipeline/runtime.pipeline— schema legacy only. The daemon does not execute pipeline mode. The compiler rejects it; migrate to aflow:graph (orcall_app).
Every behaviour and field on this page maps to real code; entries
Pattern 1 - call_app (in-agent app invocation)
call_app. An always-available primitive.
The calling agent invokes another deployed app over the daemon's
HTTP API and gets the result back as the action response.
Params (CallAppParams,)
| Field | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | Deployed app_id to call. The target must be deployed on the same daemon and runtime.mode: one_shot. |
input | string | yes | Input passed to the target's runtime.input contract. |
timeout | float | no (default 120.0) | Seconds before the call times out. |
How it works
call_app runs the installed target app in one-shot mode with
your input, waits up to timeout, and returns its output (or
an error) to the calling agent as a normal tool result.
Constraints
- Install the target first:
digitorn install target.yaml. - The target must be
runtime.mode: one_shot. - Both apps must be available in the same Digitorn instance.
- Risk level:
medium.
Example
agents:
- id: orchestrator
role: coordinator
brain: { ... }
system_prompt: |
For Python files, call_app(app_id='py-analyzer', input=path).
For TypeScript files, call_app(app_id='ts-analyzer', input=path).
Aggregate the results and present a unified report.
tools:
capabilities:
grant:
- { module: context_builder } # call_app lives here
// LLM-side
{"name": "call_app",
"arguments": {"app_id": "py-analyzer",
"input": "src/auth/validate.ts",
"timeout": 60}}
Pattern 2 - sequential chains → use flow: (not pipeline)
runtime.mode: pipeline / runtime.pipeline[] are legacy schema only.
The compiler rejects them; the daemon never executes them.
For a fixed chain of agents/tools (ETL-shaped), declare a flow:
graph with tool / agent nodes and linear routes — or
compose deployed one-shot apps via call_app from a coordinator.
runtime:
mode: background # or conversation / one_shot
entry_agent: coordinator
flow:
entry: extract
nodes:
extract:
type: agent
agent: extractor
routes: { default: classify }
classify:
type: agent
agent: classifier
routes: { default: done }
done:
type: terminal
Migrate any YAML that still has mode: pipeline to the shape above
(or to call_app steps inside an agent loop).
Pattern 3 - Multi-agent inside one app
For tightly-coupled coordination where the specialists share
workspace, memory, and the agent loop, declare them under
agents: and use the Agent(...) tool to spawn from the
coordinator. Sub-agents inherit the 5 shared modules (memory, web, lsp, filesystem, bash) - the coordinator and its
specialists see the same files and the same memory state.
This is documented in detail in Multi-Agent;
the relevant block is agents[].delegate_to, agents[].pool, and the agent_spawn.agent tool with its 8
modes.
Choosing between the three
| Need | Pick |
|---|---|
| Sub-task should run with its own daemon-managed config (different secrets, different sandbox, different deploy lifecycle). | call_app or runtime.pipeline (each app deploys independently). |
| Sub-task needs the coordinator's workspace + memory + shell session. | Multi-agent (sub-agents share the 5 modules). |
| Strictly linear workflow with stable step boundaries. | runtime.pipeline. |
| Agent decides at runtime which sub-app to call. | call_app. |
| Coordinator should fan-out in parallel to N specialists, each in its own context window. | Multi-agent (pool.max_workers + parallel Agent(...) in the same turn). |
Conditional routing (if X then app_A else app_B), approval gates, decision nodes. | flow: block. |
Cross-references
- App-config block reference for
runtime.pipeline: App Configuration → runtime - Built-in tool
call_app: Built-in Tools → always-available primitives - Multi-agent +
Agenttool: Multi-Agent - Declarative orchestration graph (richer than pipeline): Flows