Skip to main content

subagents/

Subagents live under subagents/<name>/, each with its own instructions.md and agent.ts. Add one when a task should run with a narrower identity, model, tool set, workspace, connection set, or durable run boundary.

Minimal Example

// subagents/researcher/agent.ts
import { defineSubagent } from "@assemblyline-agents/core";

export default defineSubagent({
model: "openai/gpt-5.4-mini",
reasoning: "low",
description: "Use this subagent for scoped research tasks.",
defaultTools: []
});

The description doubles as the model-facing "when to use this subagent" text, so write it as guidance for the parent model.

Full Options

defineSubagent() accepts every defineAgent() field — with model optional — plus two child-scoping fields:

FieldType / valuesDefaultEffect
modelstringinherits the primary agent's modelChild model spec.
workspaceAdapterDefinitionChild workspace adapter, e.g. adapter("local").
connectionsstring[]Connection names the child may use.
(all other defineAgent fields)see agent.tsreasoning, defaultTools, outputSchema, maxIterations, and the rest apply per child.

When the inherited model uses a built-in host route, the child uses the same route. In particular, an openai-codex/* primary agent and its inheriting subagents share the host's Codex CLI OAuth session; no child-specific auth or engine connection is required.

import { adapter, defineSubagent } from "@assemblyline-agents/core";

export default defineSubagent({
description: "Use this for durable coding sessions.",
model: "openai/gpt-5-codex",
workspace: adapter("local"),
connections: ["github"],
defaultTools: []
});

The compiler records which skills, tools, and context the subagent inherits. harness and engineConnection are intentionally not configurable: Pi is the single child-agent engine, and model-provider authentication follows model.

How The Parent Invokes A Subagent

The parent model calls the built-in spawn_subagent tool, and authored tools can call ctx.spawnSubagent(...) directly. Both take the same input:

await ctx.spawnSubagent({
name: "researcher",
task: "Summarize the three most recent issues in repo assembly-line.",
expectedOutput: "A markdown summary with issue links.",
constraints: ["Read-only: do not comment on issues."]
});

name and task are required; expectedOutput and constraints are optional. The result is the child run's JSON output.

Realtime Capabilities

Realtime services are connections and tools, not child-agent engines. For example, a Pi-backed subagent can be scoped to a LiveKit connection and invoke an authored LiveKit tool:

// subagents/caller/agent.ts
import { defineSubagent } from "@assemblyline-agents/core";

export default defineSubagent({
description: "Use this subagent to coordinate phone calls.",
connections: ["livekit"]
});

The realtime media worker still runs in LiveKit. @assemblyline-agents/livekit provides the typed API client and outbound-call tool; Assembly Line remains the reasoning and durability layer.

Conventions

  • Use defineSubagent() in subagent folders. A defineAgent() default export also compiles (some examples do this), but defineSubagent is the intended API and unlocks workspace and connections.
  • Keep each subagent's defaultTools and connections as narrow as the task allows.
  • Write description as when-to-use guidance for the parent model.