Skip to content

Latest commit

 

History

History
290 lines (213 loc) · 13.3 KB

File metadata and controls

290 lines (213 loc) · 13.3 KB

Hermes Agent — Programmatic Control Plane

Version: v1.0.0 (binding under docs/compatibility_policy.md §3 from this release) Status: Stable surface Module: mythic_vibe_cli.agent_api CLI surface: mythic-vibe surface hermes (HTTP) and mythic-vibe hermes (CLI introspection)

Hermes is the Greek messenger-god — he crosses boundaries. The Hermes Agent surface gives any external AI agent — Claude, GPT, Gemini, Aider, Goose, custom tooling — the power to see and do anything Mythic Vibe CLI exposes, through one of two access modes:

Mode For Shape
TCL (Tool Calling Library) In-process Python agents from mythic_vibe_cli.agent_api import HermesAgent — every operation is a method, every artifact readable, every state introspectable
HTTP API Any agent that speaks HTTP — non-Python clients, multi-language tooling, network-isolated agents Token-protected JSON endpoints over a stdlib HTTP server

Both modes share one core (agent_api/core.py) so behavior is identical regardless of access mode. The curated tool surface is the contract; the implementation can change without breaking callers.


1) Two access modes — one core

1.1 TCL — in-process Python (Tool Calling Library)

The Pythonic face. Drop straight into an agent loop:

from mythic_vibe_cli.agent_api import HermesAgent, build_default_agent

agent = build_default_agent(root="/path/to/project")

# Convenience methods for common queries
status = agent.status()
state = agent.state()
diagnostic = agent.doctor()

# Generic invocation by tool name + kwargs
result = agent.invoke("checkin", phase="build", update="Implemented login audit")
print(result.ok, result.value)

# Agent introspection — JSON Schema list suitable for direct
# use as the `tools` argument in Anthropic Tool Use or OpenAI
# function calling
tools = agent.list_tools()

The HermesAgent.invoke(tool, **args) method returns an InvocationResult with status (ok / error / unknown_tool / validation_error), value, error, elapsed_ms. The convenience accessors (agent.status() etc.) return the value directly for the most common queries.

1.2 HTTP API — token-protected JSON endpoints

Launch the surface:

mythic-vibe surface hermes
# ...prints:
#   URL:   http://127.0.0.1:8770/api/health
#   Token: <auto-generated 32-byte URL-safe token>
#   Tool count: 18

Or with explicit settings:

mythic-vibe surface hermes --bind 127.0.0.1 --port 8770 --token "$MY_TOKEN"

Endpoints (auth via X-Hermes-Token header OR a token field in POST bodies):

Method Path Purpose
GET /api/health No-auth health check (for reverse-proxy probes).
GET /api/tools List registered tools as JSON Schema.
POST /api/invoke Invoke a tool by name. Body: {"tool":"<name>","args":{...},"request_id":"<optional>"}.
GET /api/state Convenience for state_show.
GET /api/artifacts?under=…&glob=…&limit=… List project artifacts.
GET /api/artifacts/<relpath>?max_bytes=… Read one artifact (refuses path escapes).
GET /api/events?limit=… Recent event-log entries.

Example end-to-end:

TOKEN="<from launch output>"

# List tools
curl -H "X-Hermes-Token: $TOKEN" http://127.0.0.1:8770/api/tools

# Invoke a tool
curl -X POST -H "Content-Type: application/json" \
  -d '{"token":"'$TOKEN'","tool":"checkin","args":{"phase":"build","update":"…"}}' \
  http://127.0.0.1:8770/api/invoke

# Read an artifact
curl -H "X-Hermes-Token: $TOKEN" \
  "http://127.0.0.1:8770/api/artifacts/mythic/status.json"

2) The curated default tool registry

Eighteen tools ship in build_default_agent(). Each declares its capabilities (using the PH-20.3 plugin-capability vocabulary) and side effects so operators auditing via mythic-vibe hermes tools can see what an agent can actually touch.

Tool Capabilities Side effects Purpose
status read Project status summary
doctor read Project diagnostics
drift read docs↔code drift scan (dashboard: true for the rolled-up scorecard)
state_show read Read schema-versioned project state
checkin read, file-write writes status.json + DEVLOG.md Phase update + tracking
packet_create read, file-write writes mythic/packets/ Create reusable packet
packet_lint read Heuristic packet quality lint
verify read, subprocess, file-write runs pytest/ruff/mypy; writes VER-* Verification gates
reflect read, file-write writes mythic/handoffs/ Reflection handoff
review_architecture read Quarterly governance checklist
ai_recommend read Pure-policy model picker (zero provider calls)
provenance_verify read SHA-256 verify of plunder imports
workflow_lineage read Mermaid graph of one workflow
persona_show read Active persona (or none)
plugin_doctor read Plugin capability + breaker audit
read_artifact read Read a project-relative file (refuses path escapes)
list_artifacts read List files under a project-relative dir
recent_events read Read mythic/events.jsonl tail

The full, machine-readable list is what agent.list_tools() and GET /api/tools return — that's the source of truth.


3) Security model

The Hermes surface is asset A6 in docs/security/threat_model.md. Read both before running it.

What Hermes IS

  • A token-protected programmatic surface that exposes a curated subset of the CLI to an agent.
  • Defaulted to loopback bind (127.0.0.1). External exposure requires an explicit --bind 0.0.0.0 and a TLS reverse proxy you provide.
  • Audited: every invocation appends one line to mythic/events.jsonl via the existing PH-09 event-log primitive. Operators see exactly what an agent did.

What Hermes is NOT

  • It is not a sandbox. Agents calling Hermes can do everything the curated tools allow — including verify (which runs subprocesses) and checkin / packet_create / reflect (which mutate project state).
  • It does not enforce capability declarations at the OS level. The declarations are operator-visible documentation today (PH-20.3 vocabulary); a future subprocess sandbox could promote them to enforcement.

Hardening already in place (PH-19.0 / BS-1)

  • 32-byte URL-safe token compared via secrets.compare_digest (constant-time).
  • MAX_REQUEST_BODY_BYTES = 65_536 cap on POST bodies.
  • 30-second per-connection socket timeout.
  • Path-escape refusal in read_artifact and list_artifacts (refuses any path that resolves outside the project root).
  • Validation gate on every invocation: required-args + type + enum checks against the JSON Schema before the tool implementation runs.

Recommended deployment

Scenario Bind TLS / Proxy Notes
Local dev with an agent in the same machine 127.0.0.1 (default) none Token is sufficient; loopback only
Multi-process on the same host (agent in a sibling process) 127.0.0.1 (default) none Token in POST body or header
Remote operator → server 0.0.0.0 (explicit) required TLS reverse proxy you provide Token is the only auth — HTTPS is mandatory in production
CI / automated agent loopback inside the runner; tear down per job none Job-scoped token

4) CLI introspection

For agents that prefer "ask the CLI" over the HTTP surface:

mythic-vibe hermes tools                    # list registered tools (text or --json)
mythic-vibe hermes inspect --tool packet_create   # show one tool's full spec
mythic-vibe hermes invoke --tool status            # invoke directly without HTTP
mythic-vibe hermes invoke --tool checkin \
    --args '{"phase":"build","update":"…"}' --json

The invoke subcommand is useful for shell-script automation and operator debugging without spinning up the HTTP server. Its exit code matches the invocation result: 0 on success, 1 on operational failure / unknown tool, 2 on user input error.


5) Authoring custom tools

The default registry is built by build_default_agent(). Advanced callers can construct a HermesCore directly and register custom tools:

from mythic_vibe_cli.agent_api import (
    HermesCore, ToolSpec, Invocation, InvocationResult, HermesAgent,
)

def my_tool(core, args):
    payload = args["payload"]
    return InvocationResult(status="ok", value={"echo": payload})

core = HermesCore(root="/path/to/project")
core.register(
    ToolSpec(
        name="echo",
        description="Echo back the payload.",
        input_schema={
            "type": "object",
            "properties": {"payload": {"type": "string"}},
            "required": ["payload"],
        },
        capabilities=("read",),
    ),
    my_tool,
)

agent = HermesAgent(core)
print(agent.invoke("echo", payload="hi").value)  # {"echo": "hi"}

Custom tools can also be packaged as a Mythic plugin (see docs/PLUGIN_AUTHORING_GUIDE.md) and registered at agent-construction time by the operator's plugin loader.

Tool-author conventions

  • Always declare capabilities. Operators auditing via mythic-vibe hermes tools should see what your tool needs — read at minimum, network / subprocess / file-write if applicable.
  • Use side-effect tags for any tool that writes files or runs subprocesses. They surface in mythic-vibe hermes tools output and in GET /api/tools.
  • Don't raise into the invoker. HermesCore.invoke catches everything anyway, but a tool that returns a structured InvocationResult with status="error" and a useful error field gives the agent a much better signal than a stringified traceback.
  • Validate inputs in the JSON Schema rather than the tool body. The minimal validator in core.py enforces required + type + enum; richer validation can happen in the tool implementation.

6) Agent author quickstart — Anthropic Tool Use

Hermes tool specs are JSON-Schema-compatible. They can be passed directly to Anthropic's tools parameter:

import anthropic
from mythic_vibe_cli.agent_api import build_default_agent

agent = build_default_agent(root=".")
client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=4096,
    tools=agent.list_tools(),    # JSON Schema for every Hermes tool
    messages=[{
        "role": "user",
        "content": "Read the project status and write a one-line summary.",
    }],
)

# When Claude calls a tool, route the call through Hermes:
for block in response.content:
    if block.type == "tool_use":
        result = agent.invoke(block.name, **block.input)
        # Send result.value back to Claude as a tool_result block

Same pattern works for OpenAI function calling (the JSON Schema shape is compatible), Gemini tool calling, etc.


7) Compatibility-policy contract (v1.0)

Per docs/compatibility_policy.md §3, the Hermes surface lands in the Stable tier. From v1.0.0 onward:

  • The 18 default tool names + their input-schema shapes are SemVer-stable. New tools may be added (MINOR); existing tool fields may be added (MINOR); removals or type changes require a MAJOR bump with the documented deprecation cadence.
  • The HTTP endpoint paths + auth contract are SemVer-stable.
  • The HermesAgent / HermesCore Python class names + public method signatures are SemVer-stable.
  • The ToolSpec + Invocation + InvocationResult dataclass shapes are SemVer-stable.
  • Internal helpers (_safe_serialise, _validate_against_schema, etc.) are NOT public — they may change in any release.

8) Audit trail

Every Hermes invocation appends one line to mythic/events.jsonl via the existing PH-09 runtime/event_log primitive. Operators inspect via:

mythic-vibe hermes invoke --tool recent_events --json
# or
curl -H "X-Hermes-Token: $TOKEN" "http://127.0.0.1:8770/api/events?limit=20"
# or read the file directly:
tail -20 mythic/events.jsonl

Each audit event records tool, request_id (if supplied), status, elapsed_ms. The same event-log file is what the TUI's "Recent Events" panel reads, so Hermes invocations show up there too.


9) Reference

  • mythic_vibe_cli/agent_api/core.py — shared core (HermesCore, ToolSpec, Invocation, InvocationResult, audit emit).
  • mythic_vibe_cli/agent_api/tcl.py — Python in-process surface (HermesAgent, build_default_agent, default tool implementations).
  • mythic_vibe_cli/agent_api/http_api.py — HTTP server (HermesHttpConfig, HermesHttpServer, build_default_http_server, pure routing handlers).
  • mythic_vibe_cli/commands.pycmd_surface_hermes, cmd_hermes, cmd_hermes_tools, cmd_hermes_inspect, cmd_hermes_invoke.
  • tests/test_hermes_agent.py — 34 tests covering core + TCL.
  • tests/test_hermes_http.py — 24 tests covering HTTP API (incl. live server).
  • tests/test_hermes_cli.py — 16 tests covering CLI integration + registration.
  • docs/security/threat_model.md — asset A6 + threat rows.
  • docs/compatibility_policy.md — v1.0 SemVer rules for the Hermes surface.
  • docs/plugins.md §9a — capability-declaration vocabulary shared with Hermes ToolSpec.