Skip to main content

agentd/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2//! agentd — a minimal, MCP-native, reactive agent runtime.
3//!
4//! One binary that is CLI, daemon, and subagent re-exec. A **supervisor**
5//! owns lifecycle, triggers, and the process tree but never reasons; the
6//! **agentic loop** lives only inside subagent processes. Tools come only
7//! from MCP servers; reactivity comes from MCP resource subscriptions;
8//! agentd is itself an MCP server so agents compose with one protocol.
9//!
10//! Architecture: `rfcs/0001-mcp-native-agent-runtime.md` (front door) and
11//! `rfcs/0002`–`0013`. Binding decisions: `docs/design/00-architecture-assessment.md`.
12//! Build order: `docs/design/PLAN.md`.
13//!
14//! Module map (assessment §4.0). `agentloop` is named to avoid the `loop`
15//! keyword.
16
17pub mod a2a; // agentd 2.0 A2A surface: principals/roles/authorization + durable tasks (RFC 0029)
18#[cfg(feature = "aauth")]
19pub mod aauth; // AAuth [DRAFT] — agent-side auth for AAuth-protected MCP (RFC 0023)
20pub mod agentloop; // the in-child ReAct loop + terminal-status state machine (v2 subagents)
21pub mod auth; // endpoint credential providers + durable token cache: OAuth device/refresh, AWS, SPIFFE (RFC 0031)
22pub mod cel; // CEL expression seam (feature `cel`; always compiled, fail-closed without it)
23pub mod config; // precedence (built-in<file<env<flag) + validate-at-startup; config::{file,yaml,paths,watch}
24pub mod context; // agentd 2.0 contexts: durable transcripts, plan, memory, compaction, skills (RFC 0026 §5)
25pub mod engine; // agentd 2.0 workflow engine v3: dialect-3 model, templates, durable runs + scheduler (RFC 0027)
26pub mod exit; // the public exit-code table + terminal-status -> code map
27pub mod governor; // agentd 2.0 token governor: windowed durable budgets + tactics (RFC 0026 §7)
28pub mod identity; // instance identity from the k8s downward API (env-only, RFC 0015 §6)
29pub mod intel; // intelligence client + provider adapters
30pub mod jsonschema; // dependency-free JSON Schema subset validator (tool contracts, workflow schemas)
31// JSON-RPC 2.0 codec + framing now lives in the reusable `mcp` crate; re-export
32// so `crate::json::*` keeps resolving (MCP + the supervisor↔subagent channel).
33pub use ::mcp::rpc as json;
34pub mod mcp; // MCP client (to servers) + self-MCP server + registry/config
35// Transport primitives now live in the reusable `net` crate; re-export so
36// `crate::net::*` keeps resolving across the runtime (mcp transport + intel).
37pub use ::net;
38pub mod obs; // logging, health, tracing, metrics
39pub mod registry; // agentd 2.0 tool registry: internal > code > MCP, contracts, overrides, grants (RFC 0028)
40pub mod runtime; // agentd 2.0 runtime: event loop, turn workers, lifecycle (RFC 0026)
41pub mod sec; // secrets, tool-scope, gated exec
42pub mod sha; // dependency-free SHA-256 (content identity: workflow hashes, skill bodies, artifacts)
43pub mod signals;
44pub mod state; // agentd 2.0 durable state model: entities, manifest, inbox, timers, restore (RFC 0025)
45pub mod store; // agentd 2.0 remote state store adapters: 4-op contract over MCP tools / HTTP / memory (RFC 0025)
46pub mod subagent; // supervisor<->subagent control protocol
47pub mod supervisor; // the reactor, process tree, spawn/reap/liveness/kill/restart
48pub mod tools; // CODE-REGISTERED tools — the embedder seam (RFC 0022 §4)
49pub mod triggers; // execution modes + reactive routing + timers
50pub mod wire; // MCP + intelligence wire types // sigaction + self-pipe; SIGTERM/INT/CHLD/PIPE
51
52/// Crate version, surfaced in logs (`agentd_build_info`) and `--version`.
53pub const VERSION: &str = env!("CARGO_PKG_VERSION");
54
55/// Announce a bound loopback listener's address through `addr_file` — the
56/// discovery handshake for the built-in test mocks (`--internal-mock-llm`,
57/// `--internal-mock-mcp-http`): the harness passes a fresh path, waits for the
58/// file to exist, then reads `host:port` from it. Written atomically (tmp +
59/// rename) so a waiter never observes a half-written address.
60pub fn announce_addr(addr_file: &str, listener: &std::net::TcpListener) -> std::io::Result<()> {
61    let addr = listener.local_addr()?;
62    let tmp = format!("{addr_file}.tmp");
63    std::fs::write(&tmp, addr.to_string())?;
64    std::fs::rename(&tmp, addr_file)
65}