Daemon Mode¶
Daemon mode is where Hive becomes an agent OS. Instead of running single tasks, agents persist across cycles, generate their own goals, experience suffering, interact with each other, and live in a simulated economy.
The Heartbeat Loop¶
The HiveDaemon drives all agents in a shared loop. Each heartbeat (default 10s):
- Hot-load plugins (every 10 cycles)
- For each alive agent:
- Escalate all active stressors
- Apply suffering effects to Persona behavioral params
- If agent has an active goal: pursue it via ReAct loop
- If agent is idle: generate a new goal via ExistenceLoop (or custom GoalStrategy)
- Log suffering state, emit lifecycle events
- Auto-kill expired sub-agents
- Every 5 cycles: swarm learning across agents
- If economy enabled: process payday and roll life events
Starting the Daemon¶
CLI:
Python API:
from hive import Hive
hive = Hive()
hive.init()
hive.spawn("coder")
hive.spawn("gambler")
hive.start(heartbeat=10, cycles=50)
Goal Generation¶
When an agent has no active goal, the ExistenceLoop generates one by:
- Checking for scheduled goals due this cycle
- Checking for pending nudges from users
- Analyzing the agent's suffering state, peer activity, and recent history
- Asking the LLM to generate a goal given this context
High risk_tolerance prompts ambitious goals. High social_drive prompts collaborative goals. Low concentration causes more goal switching.
Custom Goal Strategy¶
Override goal generation with the GoalStrategy protocol:
from hive import GoalStrategy, GoalContext, Goal, HiveDaemon
from uuid import uuid4
class MyStrategy:
async def generate_goal(self, context: GoalContext) -> Goal | None:
if context.nudges:
return Goal(
goal_id=f"goal-{uuid4().hex[:8]}",
objective=f"Handle: {context.nudges[0]}",
reasoning="User nudge",
)
return None # fall through to default
daemon = HiveDaemon(hive_dir=Path(".hive"), goal_strategy=MyStrategy())
Lifecycle Hooks¶
Register callbacks for daemon events using HookRegistry:
daemon.hooks.on("goal_completed", lambda agent_id, goal_id, **kw:
print(f"{agent_id} completed {goal_id}"))
Available events:
| Event | Parameters | When |
|---|---|---|
cycle_start |
agent_id, cycle_num |
Beginning of each cycle |
cycle_end |
agent_id, cycle_num, result |
End of each cycle |
goal_generated |
agent_id, goal_id, objective |
New goal created |
goal_completed |
agent_id, goal_id |
Goal finished successfully |
goal_abandoned |
agent_id, goal_id |
Goal given up |
suffering_changed |
agent_id, suffering_state |
Suffering state updated |
Handlers can be sync or async. Exceptions in handlers are logged but don't crash the daemon.
# Async handler
async def on_suffering(agent_id: str, suffering_state: Any, **kwargs: Any) -> None:
if suffering_state.cumulative_load > 0.8:
print(f"WARNING: {agent_id} approaching crisis")
daemon.hooks.on("suffering_changed", on_suffering)
# Remove handler
daemon.hooks.off("suffering_changed", on_suffering)
Human-in-the-Loop Approvals¶
Some tools should not run without a human's say-so. Enable approvals in
.hive/config.yaml and mark which tools are gated:
approval:
enabled: true
require_for: ["shell_exec", "git_commit"] # tool names always gated
auto_approve: [] # names never gated (overrides flags)
timeout_cycles: 0 # auto-deny after N heartbeats (0 = never)
A tool can also opt in at definition time with @tool(requires_approval=True).
When a gated tool is called, the agent parks: it does not run the tool, an
approval record is persisted, and its status becomes waiting_approval. Because
agents are heartbeat-driven records (not live coroutines), the pause survives across
cycles -- each heartbeat the park gate holds the agent cheaply (no model call) until
the request is resolved. The goal stays active throughout.
Resolve from the CLI or the REST API:
hive approvals # list pending requests
hive approve ap-1a2b3c # let the tool run next cycle
hive deny ap-1a2b3c --reason "too risky" # agent sees the denial and re-plans
An approval is granted for a specific (tool, arguments) pair and is single-use:
re-running the same call later prompts again. timeout_cycles auto-denies a request
that sits unresolved too long.
Guardrails¶
Guardrails inspect content around the model -- a pre-hook on the task input and a
post-hook on the final output (the model-I/O analog of lifecycle hooks). Enable
them in .hive/config.yaml:
guardrails:
enabled: true
pii: true # redact PII in output
prompt_injection: true # block injection phrasing in input
pii_action: redact # flag | redact | block
injection_action: block # flag | redact | block
Built-ins: PII (emails, phones, SSNs, cards, IPs) and prompt injection
("ignore previous instructions", "you are now …", jailbreak phrasing). Each action is
flag (log only), redact (mask matches), or block (refuse the input / withhold the
output). A blocked input fails the task; a blocked output is replaced with a notice.
Add your own via the Guardrail protocol and GuardrailRegistry.
Life Events¶
The event engine rolls random events each cycle (30% probability). Events force agents to make decisions that affect their stats and suffering.
Event categories: career, health, social, financial, random.
How events work:
- Each cycle,
EventEngine.roll_events()checks for follow-ups and rolls a random event - The event is formatted as a prompt with numbered choices
- The agent's LLM picks a choice
- Outcomes apply stat effects (money, happiness, reputation) with a luck multiplier (mean 1.0, std 0.25)
- Some outcomes queue follow-up events for future cycles
Example event flow:
Event: "A freelance gig appeared paying $200, but it's outside your skill set."
Choice 1: Take it anyway (risky but rewarding)
Choice 2: Pass on it (safe but no income)
Choice 3: Negotiate for training time (balanced)
Agent with high risk_tolerance -> Choice 1
Luck roll: 1.4 (lucky!) -> Earns $280, gains new skill
Agent-to-Agent Protocol (A2A)¶
Agents communicate via a typed messaging system backed by JSONL files.
9 message types:
| Type | Purpose | Auto-reply type |
|---|---|---|
| REQUEST | Ask for help | RESPONSE |
| RESPONSE | Answer a request | - |
| QUERY | Ask a question | ANSWER |
| ANSWER | Answer a query | - |
| REVIEW | Request peer review | FEEDBACK |
| FEEDBACK | Provide review | - |
| DELEGATE | Assign a task | ACK or REJECT |
| ACK | Accept delegation | - |
| REJECT | Decline with reason | - |
Collaboration patterns (pre-built interaction flows):
| Pattern | Description |
|---|---|
| ReviewPattern | Code/work review between two agents |
| MentorPattern | Mentee asks mentor a question |
| DebatePattern | Two agents debate a topic in rounds |
| ChainPattern | Task passes through a chain of agents |
| SwarmTaskPattern | Task broadcast to all agents in parallel |
Semantic Memory¶
Agents can store and retrieve memories using TF-IDF similarity search.
from hive.memory.semantic import SemanticMemory
memory = SemanticMemory(hive_dir=Path(".hive"), agent_id="coder")
await memory.store("Learned that the auth module needs refactoring")
results = await memory.search("authentication issues", top_k=5)
| Method | Description |
|---|---|
store(thought, metadata) |
Store a thought, return memory_id |
search(query, top_k=5) |
Find similar memories by TF-IDF |
recall(memory_id) |
Retrieve specific memory by ID |
forget(memory_id) |
Delete a memory |
consolidate(max_age_days, min_access) |
Remove old/unused memories |
recent(limit=5) |
Get most recent memories |
Each MemoryRecord tracks: memory_id, thought, metadata, ts, access_count, last_accessed.
Checkpointing¶
Save and restore agent state snapshots for debugging or recovery.
from hive.checkpoint import CheckpointManager
mgr = CheckpointManager(hive_dir=Path(".hive"))
# Save
cp_id = mgr.save(
agent_id="coder",
label="before-risky-change",
suffering=suffering_state,
identity=identity,
ctx=execution_context,
)
# Restore
checkpoint = mgr.restore("coder", cp_id)
# Compare two checkpoints
diff = mgr.diff(checkpoint_a, checkpoint_b)
A checkpoint captures: suffering state, active goals, agent identity, world state (balance, job, skills), and persona snapshot.
Benchmarking¶
Compare model performance on identical scenarios.
CLI:
Python:
from hive.benchmark.runner import BenchmarkRunner
runner = BenchmarkRunner(hive_dir=Path(".hive"))
result = await runner.run_goal_benchmark(
models=["anthropic:lite", "openai:lite"],
cycles=5,
runs=3,
)
Results include: goals completed/abandoned, total tokens, cost, duration, and errors per model.
HTML Export¶
Export a recorded run as a standalone HTML report.
CLI:
Python:
from hive.export.html import export_html_report
export_html_report(
run_id="abc123",
logs_dir=Path(".hive/logs"),
output_path=Path("report.html"),
)
Reports include agent cards, goal timelines, notepad contents, A2A message threads, and cost tracking. Dark theme, no external dependencies.
MCP Server¶
Hive exposes itself as an MCP server so external tools (like Claude Code) can control agents.
Exposed tools: hive_init, hive_start, hive_stop, hive_status, hive_spawn, hive_kill, hive_nudge, hive_logs, hive_models.
Connect from Claude Code or any MCP client by adding to your MCP config: