Skip to content

Advanced

Sub-agents, MCP integration, lifecycle hooks, orchestration, memory, and IPC.

Sub-Agents

nca can spawn child agent sessions to handle tasks in parallel. The parent agent uses the spawn_subagent tool to delegate work.

How Sub-Agents Work

Parent Session
├── spawn_subagent(task: "write tests for auth")
│   └── Child Session (new session ID)
│       ├── Inherits conversation context summary
│       ├── Runs in isolated git worktree (optional)
│       ├── Uses bypass-permissions (no interactive prompts)
│       ├── Executes the task autonomously
│       └── Returns result to parent
└── Continues with child's output

Spawning

The agent calls spawn_subagent with:

{
    "task": "Write comprehensive tests for the authentication module",
    "focus_files": ["src/auth.rs", "src/auth/middleware.rs"],
    "use_worktree": true
}

Git Worktrees

When use_worktree is true (default), the child session runs in an isolated git worktree:

  • Worktree path: <repo>/.nca/worktrees/<session-id>
  • Branch: nca/<session-id> (created from current HEAD)
  • Changes in the worktree don’t affect the parent’s working directory

Child Session Behavior

  • Permissions: bypass-permissions (no interactive approval needed)
  • Approvals: Auto-deny handler (no blocking waits)
  • Context: Inherits a summary of the parent’s last ~10 messages
  • Timeout: 600 seconds (10 minutes)
  • Lineage: Parent and child session IDs are cross-referenced in metadata

Viewing Sub-Agents

/agents                    # List child sessions in interactive mode
nca sessions --search "child"   # Find sub-agent sessions via CLI

Sub-Agent Events

EventDescription
ChildSessionSpawnedChild session created
ChildSessionCompletedChild session finished
ChildSessionActivityIntermediate activity from child

MCP Servers

nca supports the Model Context Protocol for integrating external tool servers.

Configuration

Add MCP servers in your config:

[[mcp.servers]]
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
enabled = true

[[mcp.servers]]
name = "database"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-postgres"]
env = { DATABASE_URL = "postgresql://localhost/mydb" }
enabled = true

[[mcp.servers]]
name = "custom"
command = "/usr/local/bin/my-mcp-server"
args = ["--port", "3000"]
cwd = "/opt/my-server"
env = { API_KEY = "secret" }
enabled = true

MCP Server Config Fields

FieldTypeDefaultDescription
namestringrequiredServer identifier (used in tool names)
commandstringrequiredCommand to start the server
argsstring[][]Command arguments
envmap{}Environment variables
cwdstringWorking directory
enabledbooltrueWhether the server is active

How MCP Tools Appear

MCP tools are exposed with the naming convention:

mcp__<server_name>__<tool_name>

For example, a server named database with a tool query becomes mcp__database__query.

Listing MCP Servers

nca mcp              # CLI
nca mcp --json       # JSON output
/mcp                  # Interactive mode

Safe Mode

By default, MCP tools are not available in safe mode. To allow them:

[mcp]
expose_in_safe_mode = true

Lifecycle Hooks

Hooks let you run shell commands at various points in the session lifecycle.

Available Hook Points

HookWhen It Fires
session_startSession begins
session_endSession ends
pre_tool_useBefore a tool executes
post_tool_useAfter a tool succeeds
post_tool_failureAfter a tool fails
approval_requestedWhen user approval is needed
subagent_startWhen a sub-agent is spawned
subagent_stopWhen a sub-agent completes

Configuration

[[hooks.session_start]]
command = "echo 'Session started' >> /tmp/nca.log"
blocking = false

[[hooks.pre_tool_use]]
command = "my-audit-script --tool $NCA_TOOL_NAME"
matcher = "execute_bash"    # Only fire for bash tool
blocking = true             # Wait for completion before proceeding

[[hooks.session_end]]
command = "notify-send 'nca session ended'"
blocking = false

Hook Fields

FieldTypeDefaultDescription
commandstringrequiredShell command to execute
matcherstring""Regex pattern to filter when the hook fires
blockingboolfalseWhether to wait for the hook to complete

Persistent Memory

The memory system stores notes that persist across sessions.

CLI Commands

nca memory                                    # List all notes
nca memory list --json                        # JSON output
nca memory add "prefer async/await patterns"  # Add a note
nca memory add "uses PostgreSQL" --kind note  # With type

Interactive Commands

/memory                    # List notes
/memory always use anyhow for error handling   # Add a note

Configuration

[memory]
file_path = ".nca/memory.json"    # Storage location
max_notes = 128                    # Maximum number of notes

How Memory Works

  • Notes are stored as JSON in the workspace
  • Notes are included in the agent’s context on each turn
  • The agent can reference stored notes for consistency across sessions
  • Notes are workspace-scoped (stored in .nca/memory.json)

Orchestration

nca can be driven by external orchestrators (CI systems, automation scripts, custom tooling) via environment variables and structured output.

Orchestration Environment Variables

Set these to inject orchestration context into the session:

export NCA_ORCH_NAME="github-actions"
export NCA_ORCH_RUN_ID="run-123"
export NCA_ORCH_TASK_ID="task-456"
export NCA_ORCH_TASK_REF="PR-42"
export NCA_ORCH_PARENT_RUN_ID="parent-run-789"
export NCA_ORCH_CALLBACK_URL="https://my-ci/callback"
export NCA_ORCH_META_REPO="my-org/my-repo"
export NCA_ORCH_META_BRANCH="feature/auth"

Orchestration metadata is:

  • Stored in session state
  • Injected into the system prompt
  • Available to hooks

Headless Execution

For CI/automation, combine orchestration with non-interactive flags:

nca run \
    --prompt "run tests and report results" \
    --permission-mode bypass-permissions \
    --json \
    --stream ndjson

NDJSON Event Stream

Use --stream ndjson to get machine-readable events:

nca run --prompt "fix the build" --stream ndjson | while read -r event; do
    echo "$event" | jq '.event_type'
done

Each line is a JSON object with:

  • id — monotonic event ID
  • ts — timestamp
  • Event-specific fields (message content, tool calls, approvals, etc.)

IPC Protocol

Running sessions expose a Unix domain socket for external control.

Socket Location

$XDG_RUNTIME_DIR/nca/<session-id>.sock
# Fallback:
/tmp/nca/<session-id>.sock

Protocol

Newline-delimited JSON over Unix domain socket.

Server → Client (events):

Events are broadcast as EventEnvelope objects:

{"id": 1, "ts": "2026-04-02T10:30:00Z", "event": {"type": "MessageReceived", ...}}
{"id": 2, "ts": "2026-04-02T10:30:01Z", "event": {"type": "ToolCallStarted", ...}}

Client → Server (commands):

{"type": "SendMessage", "content": "continue with the refactoring"}
{"type": "ApproveToolCall", "call_id": "abc123"}
{"type": "DenyToolCall", "call_id": "abc123"}
{"type": "AnswerQuestion", "question_id": "q1", "answer": "option-a"}
{"type": "Cancel"}
{"type": "Shutdown"}

Event Types

EventDescription
SessionStartedSession initialized
SessionEndedSession finished (with reason)
MessageReceivedUser or assistant message
TokensStreamedStreaming token delta
CostUpdatedToken usage update
ToolCallStartedTool execution began
ToolCallCompletedTool execution finished
ApprovalRequestedWaiting for user approval
ApprovalResolvedApproval decision made
QuestionRequestedAgent asking user a question
QuestionResolvedQuestion answered
ChildSessionSpawnedSub-agent created
ChildSessionCompletedSub-agent finished
ChildSessionActivitySub-agent intermediate activity
ContextWarningContext window getting full
ContextCompactionContext was compacted
BusyStateChangedAgent state changed (Thinking, Streaming, Idle)
CheckpointSession checkpoint saved
ErrorError occurred

Custom Instructions

nca loads instructions from multiple sources, merged in order:

Loading Order

  1. Built-in system prompt — nca’s core behavior rules (disable with harness.built_in_enabled = false)
  2. AGENTS.md — project-level instructions in the workspace root
  3. .ncarc — nca-specific project instructions (configurable path)
  4. .nca/instructions.md — personal local instructions (gitignored)
  5. Skills — available skills listed for on-demand invocation
  6. Orchestration context — injected when orchestration env vars are present

AGENTS.md

Placed in the workspace root. Compatible with other AI tools (Claude Code, etc.):

## Project Rules

- Use axum for HTTP servers
- All errors must use thiserror
- Write tests for every public function

.ncarc

nca-specific project instructions:

## Stack

- Rust + Tokio async runtime
- PostgreSQL via sqlx
- Redis via deadpool-redis

## Conventions

- Module names are snake_case
- Error types end with Error
- Tests live in the same file as the code

.nca/instructions.md

Personal instructions (add to .gitignore):

## My Preferences

- I prefer verbose variable names
- Always add doc comments to public items
- Use `tracing` for logging, not `log`

Auto-Research

nca includes an auto-research feature for automated investigation:

nca autoresearch once <program> [--workspace <path>]

This runs a single automated research pass on a program or topic, generating structured output in the workspace.


Doctor Command

Run diagnostics to verify your setup:

nca doctor

Checks:

  • Configuration file validity
  • API key availability for configured providers
  • Provider connectivity
  • Required tool dependencies (git, rg)
  • File system permissions