Files
hive/core/framework/runtime/README.md
T
2026-04-07 09:18:34 -07:00

6.0 KiB

Agent Runtime

Unified execution system for all Hive agents. Every agent — single-entry or multi-entry, headless or dashboard — runs through the same runtime stack.

Topology

                     AgentRunner.load(agent_path)
                              |
                         AgentRunner
                     (factory + public API)
                              |
                       _setup_agent_runtime()
                              |
                        AgentRuntime
                   (lifecycle + orchestration)
                      /       |       \
               Stream A   Stream B   Stream C    ← one per entry point
                  |           |          |
            GraphExecutor  GraphExecutor  GraphExecutor
                  |           |          |
              Node → Node → Node  (graph traversal)

Single-entry agents get a "default" entry point automatically. There is no separate code path.

Components

Component File Role
AgentRunner runner/runner.py Load agents, configure tools/LLM, expose high-level API
AgentRuntime runtime/agent_runtime.py Lifecycle management, entry point routing, event bus
ExecutionStream runtime/execution_stream.py Per-entry-point execution queue, session persistence
GraphExecutor graph/executor.py Node traversal, tool dispatch, checkpointing
EventBus runtime/event_bus.py Pub/sub for execution events (streaming, I/O)
SharedBufferManager runtime/shared_state.py Cross-stream state with isolation levels
OutcomeAggregator runtime/outcome_aggregator.py Goal progress tracking across streams
SessionStore storage/session_store.py Session state persistence (sessions/{id}/state.json)

Programming Interface

AgentRunner (high-level)

from framework.runner import AgentRunner

# Load and run
runner = AgentRunner.load("exports/my_agent", model="anthropic/claude-sonnet-4-20250514")
result = await runner.run({"query": "hello"})

# Resume from paused session
result = await runner.run({"query": "continue"}, session_state=saved_state)

# Lifecycle
await runner.start()                           # Start the runtime
await runner.stop()                            # Stop the runtime
exec_id = await runner.trigger("default", {})  # Non-blocking trigger
entry_points = runner.get_entry_points()       # List entry points

# Context manager
async with AgentRunner.load("exports/my_agent") as runner:
    result = await runner.run({"query": "hello"})

# Cleanup
runner.cleanup()          # Synchronous
await runner.cleanup_async()  # Asynchronous

AgentRuntime (lower-level)

from framework.runtime.agent_runtime import AgentRuntime, create_agent_runtime
from framework.runtime.execution_stream import EntryPointSpec

# Create runtime with entry points
runtime = create_agent_runtime(
    graph=graph,
    goal=goal,
    storage_path=Path("~/.hive/agents/my_agent"),
    entry_points=[
        EntryPointSpec(id="default", name="Default", entry_node="start", trigger_type="manual"),
    ],
    llm=llm,
    tools=tools,
    tool_executor=tool_executor,
    checkpoint_config=checkpoint_config,
)

# Lifecycle
await runtime.start()
await runtime.stop()

# Execution
exec_id = await runtime.trigger("default", {"query": "hello"})              # Non-blocking
result = await runtime.trigger_and_wait("default", {"query": "hello"})      # Blocking
result = await runtime.trigger_and_wait("default", {}, session_state=state) # Resume

# Client-facing node I/O
await runtime.inject_input(node_id="chat", content="user response")

# Events
sub_id = runtime.subscribe_to_events(
    event_types=[EventType.CLIENT_OUTPUT_DELTA],
    handler=my_handler,
)
runtime.unsubscribe_from_events(sub_id)

# Inspection
runtime.is_running           # bool
runtime.event_bus            # EventBus
runtime.state_manager        # SharedBufferManager
runtime.get_stats()          # Runtime statistics

Execution Flow

  1. AgentRunner.run() calls AgentRuntime.trigger_and_wait()
  2. AgentRuntime routes to the ExecutionStream for the entry point
  3. ExecutionStream creates a GraphExecutor and calls execute()
  4. GraphExecutor traverses nodes, dispatches tools, manages checkpoints
  5. ExecutionResult flows back up through the stack
  6. ExecutionStream writes session state to disk

Session Resume

All execution paths support session resume:

# First run (agent pauses at a client-facing node)
result = await runner.run({"query": "start task"})
# result.paused_at = "review-node"
# result.session_state = {"memory": {...}, "paused_at": "review-node", ...}

# Resume
result = await runner.run({"input": "approved"}, session_state=result.session_state)

Session state flows: AgentRunner.run()AgentRuntime.trigger_and_wait()ExecutionStream.execute()GraphExecutor.execute().

Checkpoints are saved at node boundaries (sessions/{id}/checkpoints/) for crash recovery.

Event Bus

The EventBus provides real-time execution visibility:

Event When
NODE_STARTED Node begins execution
NODE_COMPLETED Node finishes
TOOL_CALL_STARTED Tool invocation begins
TOOL_CALL_COMPLETED Tool invocation finishes
CLIENT_OUTPUT_DELTA Agent streams text to user
CLIENT_INPUT_REQUESTED Agent needs user input
EXECUTION_COMPLETED Full execution finishes

In headless mode, AgentRunner subscribes to CLIENT_OUTPUT_DELTA and CLIENT_INPUT_REQUESTED to print output and read stdin. The web dashboard subscribes to route events to the frontend.

Storage Layout

~/.hive/agents/{agent_name}/
  sessions/
    session_YYYYMMDD_HHMMSS_{uuid}/
      state.json              # Session state (status, memory, progress)
      checkpoints/            # Node-boundary snapshots
      logs/
        summary.json          # Execution summary
        details.jsonl         # Detailed event log
        tool_logs.jsonl       # Tool call log
  runtime_logs/               # Cross-session runtime logs