Teams

Teams are a harness pattern built from named agent definitions plus the unified task delegation core. A3S Code does not expose a separate team runner API; the parent session stays responsible for synthesis, policy, and final verification.

  1. Put durable roles in .a3s/agents or configure additional agentDirs.
  2. Keep each role focused: description, prompt, allowed tools, denied tools.
  3. Enable autoDelegation when the runtime should select high-confidence subagents.
  4. Use session.task(...) or session.tasks(...) when the host already knows the lanes.
  5. Merge child summaries, evidence references, and risks in the parent.
TypeScript
const session = agent.session('/repo', {
agentDirs: ['./.a3s/agents'],
planningMode: 'auto',
autoDelegation: { enabled: true, maxTasks: 4 },
maxParallelTasks: 8,
});
await session.send(`
Build a release-readiness team:
- explorer: find risky changed areas
- tester: identify missing verification
- security: review side-effect paths
Use independent subagents where useful and return a single prioritized report.
`);

Custom Agent Files

Markdown agent files use Claude-compatible frontmatter, with A3S-native placement under .a3s/agents:

Markdown
---
name: release-reviewer
description: Use proactively after release or CI changes
tools: Read, Search, Bash(cargo test*)
disallowedTools:
- Write
- Bash(git push*)
---
Review release blockers first, then risks, then follow-up work.

Tool names match case-insensitively, and an entry with parentheses such as Bash(cargo test*) is kept as a permission pattern. Listing tools makes the agent allow-only; disallowedTools entries are added as deny rules.

A3S also reads .claude/agents as a migration source. Prefer .a3s/agents for new projects.

Built-in Team Roles

Use these without creating files:

  • explore: read-only repository exploration
  • plan: read-only implementation planning
  • general / general-purpose: multi-step implementation
  • verification: checks, repros, and regression validation
  • review: findings-first code review

Manual Lanes

SDK callers can call direct helpers when the host already knows the lanes:

TypeScript
const result = await session.tasks([
{
agent: 'explore',
description: 'Changed files',
prompt: 'Find risky changed files.',
},
{
agent: 'verification',
description: 'Test gaps',
prompt: 'Find missing verification.',
},
{
agent: 'review',
description: 'Regression review',
prompt: 'Review correctness risks.',
},
]);
if (result.exitCode !== 0) throw new Error(result.output);
console.log(result.output);

session.tasks(...) is the host-driven multi-item wrapper around task; it returns a ToolResult, not a StepOutcome[]. Use session.parallel(...) when you need one structured outcome per lane.

When the team's lane structure is fixed and should be reproducible and resumable rather than model-chosen, use the programmable combinators in Orchestration (session.parallel / session.pipeline / session.parallelResumable).

Worker Agents

Register disposable worker agents with workerAgents or registerWorkerAgent() when the role is constructed by the host instead of stored on disk:

TypeScript
const session = agent.session('/repo', {
workerAgents: [
{
name: 'frontend-worker',
description: 'Small verified frontend fixes',
kind: 'implementer',
model: 'provider/model-id',
maxSteps: 24,
confirmationInheritance: 'auto_approve',
},
],
});

Control how child runs resolve Ask decisions with confirmationInheritance:

  • 'auto_approve': the child's own Ask decisions are approved automatically (default for agents with allow or deny permission rules)
  • 'deny_on_ask': the child's own Ask decisions are denied (default for agents without permission rules)
  • 'inherit_parent': the child's Ask decisions go to the parent session's confirmation provider

See Tasks for details.

Runtime State

Each delegated child is tracked by task ID. Read snapshots with subagentTasks() / pendingSubagentTasks() (Python subagent_tasks() / pending_subagent_tasks(), Go SubagentTasks / PendingSubagentTasks), cancel one child with cancelSubagentTask(taskId), and cancel the parent run with cancelRun(runId). Streaming events and run replay (runEvents(runId)) carry the same task IDs for UI state.