How to use

Start with install, then the core path

These notes describe the shipped local runtime: claim, gate, fail-closed, reconcile, and record evidence. Hosted team storage is planned, not live.

Start

Install

Requires Python 3.10 or later.

pip install mycelium-runtime
pip install 'mycelium-runtime[langgraph]'   # automatic ToolRuntime IDs
pip install 'mycelium-runtime[redis]'   # optional
pip install 'mycelium-runtime[postgres]'

mycelium init              # on-ramp (transition + one ledgered tool)
mycelium init --full       # reference: all guards (fill TODOs; not default)
mycelium init --minimal    # smaller multi-guard scaffold
mycelium demo              # feature tour: unguarded vs ledgered + gates / hard-block / release
mycelium demo --redis      # optional Cloud-style 2-worker Redis proof
mycelium run --config mycelium.yaml -- python -m my_agent

Agent-assisted setup

The repository includes a $mycelium-setup skill for coding agents. Ask the agent to use it in your project. It inventories tool entry points, proposes side-effect classifications, writes or updates mycelium.yaml, wires supported runtimes, adds focused tests, and runs Doctor and Verify.

Use $mycelium-setup to protect this project.

The skill does not invent signing keys, provider credentials, business request IDs, production namespaces, or approval policy. Review consequential tool classifications and supply those host-owned values yourself. The generated YAML remains ordinary project configuration that you can inspect and edit.

How it fits

Mycelium sits between the agent loop and your tools: after the LLM returns tool_calls, around execution. Its execution control proves run-or-not and enforces at-most-once.

What it does

Control areas. mycelium init / mycelium run begin with durable side-effect protection at the tool boundary.

Core

Actions (core)

Transition ledger for safe execution: the default mycelium init / mycelium run path. Each ledgered tool gets a side_effect_class and transition_key. Repeated dispatches resolve through gates, not blind re-execution. Read the prevention page →

from mycelium import load_config

config = load_config("mycelium.yaml")

@config.apply
def send_payment(amount: float, recipient: str) -> dict:
    return gateway.charge(amount, recipient)

# payment: duplicate resolves existing transition; won't charge twice
send_payment(amount=100.0, recipient="acct_123", tool_call_id="call_pay")

See Resolution for gate semantics and the SDK README for the full reference.

Resolution

Invariant: do not redispatch unless the previous transition is proven terminal or safely recoverable. See the resolution gates →

Envelope fields (core)

Six fields decide whether an unresolved prior execution is merely wasteful or unsafe.

YAML

transition:
  agent_id: payment-agent
  policy_version: "2026.07.1"
  lease_ttl: 3600

action_ledger:
  storage: file
  path: ./mycelium-ledger.json

Unified durable state

Loop, scope, completion, state-flush, and audit-receipt guards can share one namespaced atomic backend. A guard with no local storage setting inherits it automatically, including guards you enable later.

state_backend:
  storage: postgres        # memory | file | redis | postgres
  dsn_env: DATABASE_URL
  namespace: payments-prod

loop_guard: {}
completion:
  required: [payment_recorded]

Use file for one node and Redis or Postgres for multiple workers. To move old guard state, stop workers, keep the legacy per-guard storage configured, run the copy, then switch those guards to inherited or shared storage:

mycelium state migrate --plan --config mycelium.yaml
mycelium state migrate --apply --config mycelium.yaml
mycelium doctor --config mycelium.yaml --strict

Migration is copy-only and refuses conflicts. Rollback means pointing the guard back to its unchanged legacy storage.

Provider adapter conformance

A reconciler decides whether an ambiguous operation completed. A false NOT_EXECUTED permits another attempt, so every adapter needs adversarial tests. Gmail is the only adapter currently shipped. Other providers implement the same conformance fixture and supply provider-specific scripted observations.

export MYCELIUM_ADAPTER_REPORT_SIGNING_KEY='from-your-secret-manager'
mycelium providers verify gmail \
  --key-id provider-ci-2026-01 \
  --output gmail-adapter-report.json
mycelium providers verify-report gmail-adapter-report.json --json

The key signs the report with HMAC-SHA256 so CI or an operator can detect edits and verify which adapter source passed. Mycelium itself works without this key; it is required only when creating or checking an adapter-verification report. The report proves the synthetic suite passed and the source still matches. It does not prove live credentials are read-only, so enforce provider scopes separately.

Opt-in

Context (opt-in)

TTL cache and message/history helpers.

Tool boundaries (opt-in)

Input/output/scope validation and allowlists.

Loop guard (opt-in)

Detects identical tool+args across new tool_call_ids.

Completion contract (opt-in)

Refuses terminal while required subtasks are pending.

Scope guard (opt-in)

Freezes the run tool allowlist and re-checks every step.

Secret-in-args (opt-in)

Blocks raw credentials before claim. Pass secret:// references instead of API keys. Fail-closed pre-execution blocking is the primary protection; redaction is defense-in-depth. Mycelium cannot sanitize logs created inside application or provider code.

Outcome telemetry & DTTR (v1.20+)

Opt-in flat append-only outcome rows for production observability.

Reference

Failure-mode catalog

Stable IDs used in the SDK README, changelogs, and this handbook. The public story leads with outcomes, not a guardrail count. Browse the prevention catalog →

API

See SDK README for the full export list.

Common searches

FAQ content for production reliability, LangGraph duplicates, and idempotency. Read about Verify →