Skip to main content

App Composition

Three ways to combine Digitorn apps. Each serves a different shape of workflow.

PatternMechanismWhen to use
call_app toolOne agent calls another deployed app as a tool, in-flight.Ad-hoc composition; agent decides at runtime which apps to invoke.
flow: graphIn-app workflow (agents, tools, IF, parallel). Prefer this for linear/branching automation.Background or conversation apps that need deterministic routing.
Multi-agentOne 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 a flow: graph (or call_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,)

FieldTypeRequiredDescription
app_idstringyesDeployed app_id to call. The target must be deployed on the same daemon and runtime.mode: one_shot.
inputstringyesInput passed to the target's runtime.input contract.
timeoutfloatno (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

yaml
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
json
// 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.

app.yaml (preferred)
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

NeedPick
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