Agents and Lifecycle

What is an Agent?

An agent in Scarab-Runtime is a process spawned and managed by agentd. Unlike ordinary OS processes, every agent has:

  • A UUID identity (SCARAB_AGENT_ID) injected at spawn time
  • A lifecycle state tracked by the daemon
  • A capability set derived from its manifest
  • A sandbox enforced at the kernel level
  • An audit trail of every action it takes
  • A workspace (overlay filesystem) for isolated file operations
  • A persistent memory store (SQLite-backed key-value)
  • An observation log (hash-chained NDJSON)

Lifecycle State Machine

Every agent follows this state machine:

Agent lifecycle state machine

Terminate is reachable from any state except Init.

State Descriptions

StateDescription
InitAgent is being set up. Sandbox, cgroups, and capability profiles are applied. The agent binary has not yet received control.
PlanAgent is reasoning. Typically calls agent.plan() to declare steps, may read memory or query observations.
ActAgent is executing. Tool invocations are expected in this state.
ObserveAgent is processing results. Typically calls agent.observe() to record what happened.
TerminateAgent is shutting down. Resources are released and the audit log entry is finalized.

State Transitions

Agents transition by calling agent.transition(state) (via the SDK) or by receiving an IPC Transition request. Transitions are validated:

  • Init → Plan is the first valid transition after spawn
  • Plan ↔ Act ↔ Observe are the normal loop states
  • Terminate from any non-Init state is always valid
  • Invalid transitions return an error without changing state

Operators can force a transition with ash transition <agent-id> <state>.

Agent Identity

When agentd spawns an agent, it injects:

SCARAB_AGENT_ID=<uuid>          # Agent's unique identifier
SCARAB_SOCKET=/run/agentd/agentd.sock  # Path to daemon socket
SCARAB_TASK=<text>              # From spec.task (if set)
SCARAB_MODEL=<model-id>         # From spec.model (if set)

The agent binary reads these with std::env::var or the Agent::from_env() SDK helper.

Agent Hierarchy

Agents form a tree. The agent that spawns another becomes its parent. Escalations (capability requests, anomaly alerts) travel up the tree. The root agent escalates to the human HITL gate.

Agent hierarchy tree

Discover Agents

Agents can discover each other by capability pattern:

ash discover <agent-id> "bus.*"

This finds all running agents that have any bus.* capability.