[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81816":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":12,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":13,"stars7d":13,"stars30d":13,"stars90d":13,"forks30d":13,"starsTrendScore":13,"compositeScore":14,"rankGlobal":10,"rankLanguage":10,"license":15,"archived":16,"fork":16,"defaultBranch":17,"hasWiki":18,"hasPages":18,"topics":19,"createdAt":10,"pushedAt":10,"updatedAt":20,"readmeContent":21,"aiSummary":22,"trendingCount":13,"starSnapshotCount":13,"syncStatus":23,"lastSyncTime":24,"discoverSource":25},81816,"agentd","guozijn\u002Fagentd","guozijn","State Machine Daemon designed specifically to orchestrate and persist the state of AI agents","https:\u002F\u002Fblog.zjguo.com\u002Fagentd\u002F",null,"Rust",33,0,40,"MIT License",false,"main",true,[],"2026-06-12 04:01:35","# agentd\n\n`agentd` is a local-first state machine daemon for AI agents. It runs out of process, stores task state in SQLite, and exposes a Unix Domain Socket (UDS) JSON Lines API so agent runtimes can coordinate long-running DAG work without becoming the source of truth.\n\n## Features\n\n- Durable SQLite state under `~\u002F.agentd`\n- Strict DAG node states: `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`\n- Lease-based node acquisition with heartbeat and timeout rollback\n- Cross-provider resource locks for repository files and other shared resources\n- Append-only event journal\n- Provider-neutral conflict resolution with lock metadata, event history, and patch bundles\n- Runtime interface discovery: `DescribeInterface`\n- Health and metrics endpoints: `Health`, `Metrics`\n- Versioned schema migrations\n- Real DeepSeek multi-agent loop example\n\n## Install \u002F Run\n\nDevelopment:\n\n```bash\ncargo run\n```\n\nBuilt binary:\n\n```bash\ncargo build --release\n.\u002Ftarget\u002Frelease\u002Fagentd\n```\n\nDownloaded release binary:\n\n```bash\n.\u002Fagentd\n```\n\nCargo is not required to run a built or downloaded binary.\n\n## Default Paths\n\n| Item | Default |\n| --- | --- |\n| Env file | `~\u002F.agentd\u002F.env` |\n| SQLite DB | `~\u002F.agentd\u002Fagent_state.db` |\n| UDS socket | `~\u002F.agentd\u002Fagentd.sock` |\n\nProcess environment variables override values from the env file.\n\n## Configuration\n\nCreate config:\n\n```bash\nmkdir -p ~\u002F.agentd\ncp .env.example ~\u002F.agentd\u002F.env\nchmod 600 ~\u002F.agentd\u002F.env\n```\n\nImportant variables:\n\n| Variable | Default | Purpose |\n| --- | --- | --- |\n| `AGENTD_ENV_FILE` | `~\u002F.agentd\u002F.env` | Env file path |\n| `AGENTD_HOME` | `~\u002F.agentd` | Base state directory |\n| `AGENTD_DATABASE_URL` | `sqlite:\u002F\u002F~\u002F.agentd\u002Fagent_state.db` | SQLite URL |\n| `AGENTD_SOCKET_PATH` | `~\u002F.agentd\u002Fagentd.sock` | UDS path |\n| `AGENTD_NODE_TIMEOUT_SECS` | `300` | Lease timeout |\n| `AGENTD_CONTEXT_EVENT_LIMIT` | `50` | Recent events included in acquired-node context |\n| `RUST_LOG` | `agentd=info` | Logging filter |\n\nDeepSeek loop variables:\n\n| Variable | Default |\n| --- | --- |\n| `DEEPSEEK_API_KEY` | required |\n| `DEEPSEEK_BASE_URL` | `https:\u002F\u002Fapi.deepseek.com` |\n| `DEEPSEEK_MODEL` | `deepseek-v4-flash` |\n| `DEEPSEEK_MAX_TOKENS` | `120` |\n| `DEEPSEEK_TEMPERATURE` | `0.2` |\n| `AGENTD_AGENT_WORKERS` | `2` |\n| `AGENTD_ARTIFACT_DIR` | `~\u002F.agentd\u002Fartifacts` |\n\n## IPC Protocol\n\nTransport: Unix Domain Socket\n\nFraming: one JSON request per line, one JSON response per line\n\nRequest:\n\n```json\n{\"id\":1,\"method\":\"Health\",\"params\":{}}\n```\n\nResponse:\n\n```json\n{\"id\":1,\"result\":{\"status\":\"ok\",\"database\":\"ok\",\"running_timeout_secs\":300,\"context_event_limit\":50}}\n```\n\nSupported methods:\n\n| Method | Purpose |\n| --- | --- |\n| `DescribeInterface` | Return protocol and method schema |\n| `Health` | Check daemon and SQLite readiness |\n| `Metrics` | Return runtime counters and DB gauges |\n| `RegisterTask` | Create a task and DAG nodes |\n| `AcquireNextNode` | Lease the next runnable node |\n| `CommitEvent` | Append a journal event |\n| `HeartbeatNode` | Extend a node lease |\n| `CompleteNode` | Complete a leased node |\n| `FailNode` | Fail a leased node |\n| `TaskStatus` | Return task and node state |\n| `AcquireResourceLock` | Lease a named resource such as `file:src\u002Flib.rs` |\n| `HeartbeatResourceLock` | Extend a resource lock lease |\n| `ReleaseResourceLock` | Release a resource lock lease |\n| `ListResourceLocks` | Return active resource locks |\n\nAgents should call `DescribeInterface` when they do not have a generated or built-in client.\n\nQuery it from a shell:\n\n```bash\nprintf '%s\\n' '{\"id\":1,\"method\":\"DescribeInterface\",\"params\":{}}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\n## Node Leases\n\n`AcquireNextNode` returns:\n\n- `node_id`\n- `lease_id`\n- `lease_owner`\n- `lease_expires_at`\n- synthesised execution context\n\nWorkers must pass the current `lease_id` to `CommitEvent`, `HeartbeatNode`, `CompleteNode`, and `FailNode`. If a worker stalls past `AGENTD_NODE_TIMEOUT_SECS`, the daemon rolls the node back to `PENDING`; a later worker gets a new lease, and stale lease writes are rejected.\n\n## Cross-provider Repository Locks\n\nAgents from different providers can collaborate in one repository by using `agentd` as the local coordination point. Before editing a file or other shared resource, acquire an exclusive resource lock with a stable `resource_key`.\n\nRecommended key formats:\n\n| Resource | Key example |\n| --- | --- |\n| Single file | `file:src\u002Flib.rs` |\n| Directory-wide operation | `dir:src` |\n| Generated artifact | `artifact:docs\u002Fapi.json` |\n| External tool | `tool:cargo-fmt` |\n\nAcquire a file lock:\n\n```bash\nprintf '%s\\n' '{\n  \"id\": 1,\n  \"method\": \"AcquireResourceLock\",\n  \"params\": {\n    \"resource_key\": \"file:src\u002Flib.rs\",\n    \"owner\": \"codex-cli\",\n    \"provider\": \"openai\",\n    \"ttl_secs\": 300,\n    \"metadata\": {\"intent\": \"edit\"}\n  }\n}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\nIf the resource is already held, the result is `null`. If the lock is granted, the result includes a `lease_id`. The agent must pass that `lease_id` to `HeartbeatResourceLock` while working and to `ReleaseResourceLock` when finished.\n\nRelease a file lock:\n\n```bash\nprintf '%s\\n' '{\n  \"id\": 2,\n  \"method\": \"ReleaseResourceLock\",\n  \"params\": {\n    \"resource_key\": \"file:src\u002Flib.rs\",\n    \"lease_id\": \"current-lease-uuid\"\n  }\n}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\nThis is provider-agnostic: Codex, Claude Code, DeepSeek scripts, local shell agents, or custom clients all use the same Unix socket and SQLite-backed lease table. Expired locks are recoverable; a later agent can acquire the same `resource_key` after the previous lease times out.\n\n## Multi-provider Conflict Resolution\n\nUse `agentd` as the local coordination layer when multiple providers can edit the same repository, for example two Codex workers and an Antigravity-style agent working on `docs\u002Findex.html`.\n\nThe default policy is:\n\n- Prevent high-risk overlap with narrow `AcquireResourceLock` leases.\n- Put provider-neutral patch metadata in lock `metadata`: base revision, touched paths, diff summary, assumptions, confidence, and planned verification.\n- When work runs inside an agentd task, append `CommitEvent` entries for `intent`, `progress`, `result`, and `conflict`.\n- If providers overlap, compare base revision, touched paths, intent, confidence, and verification output.\n- Merge compatible edits, reject stale or unverifiable edits, and record the accepted decision.\n- Do not use last-writer-wins as the merge policy.\n\nReal scenario: Codex starts a docs edit and Antigravity attempts the same file.\n\nCodex acquires the file lock with patch-bundle metadata:\n\n```bash\nprintf '%s\\n' '{\n  \"id\": 10,\n  \"method\": \"AcquireResourceLock\",\n  \"params\": {\n    \"resource_key\": \"file:docs\u002Findex.html\",\n    \"owner\": \"codex-docs-agent-a\",\n    \"provider\": \"openai\",\n    \"ttl_secs\": 600,\n    \"metadata\": {\n      \"intent\": \"add multi-provider conflict resolution docs\",\n      \"base_revision\": \"git:HEAD\",\n      \"touched_paths\": [\"docs\u002Findex.html\", \"docs\u002Fstyles.css\", \"README.md\"],\n      \"diff_summary\": \"document provider-neutral conflict policy and add animated flow\",\n      \"assumptions\": [\"static HTML site\", \"CSS-only animation\"],\n      \"confidence\": \"medium\",\n      \"verification\": [\"python3 HTML parser sanity check\"]\n    }\n  }\n}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\nIf Antigravity tries to acquire the same file while Codex holds it, it receives `null`:\n\n```bash\nprintf '%s\\n' '{\n  \"id\": 11,\n  \"method\": \"AcquireResourceLock\",\n  \"params\": {\n    \"resource_key\": \"file:docs\u002Findex.html\",\n    \"owner\": \"antigravity-docs-agent\",\n    \"provider\": \"antigravity\",\n    \"ttl_secs\": 600,\n    \"metadata\": {\n      \"intent\": \"rewrite docs conflict section\",\n      \"base_revision\": \"git:HEAD\",\n      \"touched_paths\": [\"docs\u002Findex.html\"],\n      \"diff_summary\": \"replace conflict section with provider workflow\",\n      \"confidence\": \"medium\"\n    }\n  }\n}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\nThe coordinator should then choose one of these paths:\n\n| Situation | Coordinator action |\n| --- | --- |\n| Same file, incompatible intent | Keep the first lock, ask the second provider to wait or narrow scope |\n| Same file, compatible intent | Let the second provider produce a patch bundle without writing, then merge manually |\n| Stale base revision | Ask the stale provider to rebase before integration |\n| Failed verification | Reject that provider result and record the reason |\n\nWhen the work is part of a registered DAG node, record the provider trail with `CommitEvent`:\n\n```bash\nprintf '%s\\n' '{\n  \"id\": 12,\n  \"method\": \"CommitEvent\",\n  \"params\": {\n    \"task_id\": \"current-task-uuid\",\n    \"node_id\": \"current-node-uuid\",\n    \"lease_id\": \"current-node-lease-uuid\",\n    \"action_type\": \"conflict\",\n    \"payload\": {\n      \"resource_key\": \"file:docs\u002Findex.html\",\n      \"providers\": [\"openai\", \"antigravity\"],\n      \"resolution\": \"merged Codex lock-first metadata with Antigravity patch-bundle proposal\",\n      \"accepted_paths\": [\"docs\u002Findex.html\", \"docs\u002Fstyles.css\", \"README.md\"],\n      \"rejected_alternatives\": [\"last-writer-wins\"],\n      \"verification\": \"HTML parser sanity check passed\"\n    }\n  }\n}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\nAfter verification, release the file lock:\n\n```bash\nprintf '%s\\n' '{\n  \"id\": 13,\n  \"method\": \"ReleaseResourceLock\",\n  \"params\": {\n    \"resource_key\": \"file:docs\u002Findex.html\",\n    \"lease_id\": \"current-resource-lock-lease-uuid\"\n  }\n}' | nc -U ~\u002F.agentd\u002Fagentd.sock | python3 -m json.tool\n```\n\n## Smoke Tests\n\nStart daemon:\n\n```bash\ncargo run\n```\n\nBasic Python client:\n\n```bash\npython3 client_test.py\n```\n\nReal DeepSeek multi-agent loop:\n\n```bash\npython3 scripts\u002Fdeepseek_agent_loop.py\n```\n\nThe DeepSeek loop registers a four-node DAG: one agent writes a compact Python worker script, one concurrently writes the IPC contract, one waits for both and reviews integration safety, and one waits last to synthesise the result. Generated artifacts are written under `~\u002F.agentd\u002Fartifacts` by default.\n","agentd 是一个专为AI代理设计的状态机守护进程，旨在协调和持久化AI代理的任务状态。它使用Rust编写，通过SQLite存储任务状态，并提供基于Unix域套接字的JSON Lines API接口，允许代理运行时协调长时间运行的工作流而无需成为事实来源。核心功能包括严格定义的DAG节点状态、基于租约的节点获取机制、跨提供商资源锁以及版本化的模式迁移等。适用于需要对复杂AI工作流进行可靠管理和持久化的场景，如多代理协作环境下的任务调度与执行跟踪。",2,"2026-06-11 04:06:50","CREATED_QUERY"]