Local-first infrastructure for agent state

agentd

An out-of-process state machine daemon for AI agents. It owns durable task state, strict DAG transitions, file locks, heartbeats, and an append-only event journal.

What it does

One local source of truth for long-running agent work.

Durable state

SQLite stores global tasks, DAG nodes, result payloads, and event history under ~/.agentd.

Strict transitions

Nodes move through PENDING, RUNNING, COMPLETED, or FAILED.

Lease safety

Workers acquire leases, heartbeat while running, and stale work rolls back to PENDING.

Repository locks

Agents from different providers can lease resource keys such as file:src/lib.rs before editing.

Conflict resolution

Overlapping Codex, Antigravity, or custom-agent edits can be compared as patch bundles instead of last writer wins.

Model agnostic

Python, Node, Rust, and shell clients can coordinate through Unix Domain Socket JSON Lines IPC.

Low overhead

No network service is required. The daemon runs locally as a small Rust binary.

Runtime discovery

Agents can call DescribeInterface to learn supported methods and payload shapes.

Conflict resolution

Make concurrent agent edits inspectable before they merge.

agentd gives coordinators a provider-neutral handoff for Codex, Antigravity, DeepSeek scripts, and custom agents: resource locks, journaled intent, and patch bundles that can be compared before integration.

Codex A Lock first
Codex B Journal first
Antigravity Patch bundle
01

Prevent high-risk overlap with narrow locks for files, modules, generated artifacts, or logical work units.

02

Require each provider to emit intent, progress, result, and conflict events.

03

Compare patch bundles by base revision, touched paths, diff summary, assumptions, confidence, and verification output.

04

Merge compatible edits, reject stale or unverifiable changes, and record the accepted decision.

Runtime interface

Ask the daemon what it supports.

The IPC contract is discoverable at runtime. Send one JSON object per line to the Unix socket and read one JSON response per line.

DescribeInterface
RegisterTask
AcquireNextNode
CommitEvent
HeartbeatNode
CompleteNode
FailNode
TaskStatus
AcquireResourceLock
HeartbeatResourceLock
ReleaseResourceLock
ListResourceLocks
printf '%s\n' '{"id":1,"method":"DescribeInterface","params":{}}' \
  | nc -U ~/.agentd/agentd.sock \
  | python3 -m json.tool