Skip to content

cllama: The Governance Proxy

When a reasoning model tries to govern itself, the guardrails are part of the same cognitive process they are trying to constrain. This is the fundamental problem with prompt-level safety: the judge and the defendant share the same brain.

cllama is a separate process sitting between the runner and the LLM provider. The runner thinks it is talking directly to the model. It never sees the proxy. This is principle number eight: think twice, act once.

How It Works

The proxy sits on the network path between every agent in the pod and the LLM providers. When an agent makes an API call to what it believes is OpenAI or Anthropic, the request goes to cllama instead. The proxy evaluates, routes, and logs the request, then forwards it to the real provider.

Agent → (bearer token) → cllama proxy → (real API key) → LLM Provider

                     audit log + dashboard

A single proxy instance serves the entire pod. Bearer tokens resolve which agent is calling, so the proxy can apply per-agent policy, budgets, and logging.

Credential Starvation

Isolation is achieved by strictly separating secrets:

  • The proxy holds the real API keys. Provider credentials (OpenRouter, Anthropic, OpenAI) are configured in the pod-level cllama-defaults.env block and never enter agent containers.
  • Agents get unique bearer tokens. Each agent (and each ordinal of a scaled agent) receives a unique token generated during claw up.
  • No credentials, no bypass. Because agents lack the credentials to call providers directly, all successful inference must pass through the proxy -- even if a malicious prompt tricks the agent into ignoring its configured base URL.

Keys Never Enter Agent Containers

Provider API keys belong in x-claw.cllama-defaults.env at the pod level. They are injected into the cllama proxy container only. Agent containers receive bearer tokens, not API keys.

Identity Resolution

The proxy uses bearer tokens to resolve caller identity. Each token maps to a specific agent (or agent ordinal), which means the proxy can:

  • Apply per-agent policy and cost budgets
  • Track per-agent token usage and spend
  • Log which agent made which request
  • Enforce different model access per agent

The token format is <agent-id>:<secret>, generated fresh on every claw up. The proxy loads a principals file mapping tokens to agent identities and their compiled contract context.

When a request arrives, the proxy:

  1. Extracts the <agent-id> from the bearer token.
  2. Loads the agent's context from CLAW_CONTEXT_ROOT/<agent-id>/.
  3. Validates the <secure-secret> against metadata.json principals.
  4. Checks the requested model against the agent's allowed models.

Token validation is fail-closed: unknown or missing tokens are denied before any provider call is made.

Transport Model

The proxy exposes an HTTP API compatible with the OpenAI Chat Completions API.

PropertyValue
EndpointPOST /v1/chat/completions
Listen port0.0.0.0:8080
Base URL (as seen by runner)http://cllama-<type>:8080/v1
Auth headerAuthorization: Bearer <agent-id>:<secure-secret>

Clawdapus configures each agent's runner to use the proxy URL as its LLM base URL. The runner thinks it is talking directly to the model provider. Two distinct code paths handle OpenAI format (messages[]) and Anthropic format (top-level system field).

OpenAI Format

Requests to /v1/chat/completions are handled as OpenAI format. The payload contains a messages[] array and a model field. The proxy rewrites the model field to the operator-assigned provider and model, then forwards the request to the resolved upstream endpoint.

Anthropic Format

Requests to /v1/messages are handled as Anthropic format. The payload uses a top-level system field rather than embedding system messages in the messages array. The proxy forwards Anthropic-specific headers (Anthropic-Version, Anthropic-Beta) and routes directly to the Anthropic provider.

Format Bridging

When the resolved provider uses Anthropic format but the incoming request is OpenAI format (/v1/chat/completions), the proxy routes through OpenRouter instead, which accepts OpenAI format for all models. This transparent bridging means agents do not need to know which provider or format their assigned model requires.

Pure Passthrough

In passthrough mode, the proxy rewrites the model field and forwards. It does not touch the messages array. No prompt decoration, no system message injection -- those capabilities are reserved for the cllama-policy proxy type.

The Interception Pipeline

The cllama specification defines a full bidirectional interception pipeline with five phases. The runner never knows the proxy exists -- it thinks it is talking directly to the model.

Pre-flight

Identity resolution, token validation, and model authorization. Invalid tokens are rejected before any downstream work begins.

Outbound Interception (Agent to Provider)

Before the LLM sees the prompt, the proxy can evaluate and modify the outbound request:

  • Context aggregation -- The proxy parses the enforce rules from the agent-specific AGENTS.md. These rules form the behavioral contract that governs what the agent is allowed to do.
  • Tool scoping -- If the agent's request contains tools, the proxy evaluates each tool against the agent's identity and active policy modules. Tools not authorized for the agent's contracted role are silently dropped before the request reaches the provider.
  • Prompt decoration (pre-prompting) -- The proxy may modify the outbound messages array to inject operator-defined rules, priorities, or warnings. This decoration happens transparently -- the agent has no visibility into what was added.
  • Policy blocking -- If the outbound prompt violates a loaded policy module or enforce rule, the proxy may short-circuit the request entirely and return an error or a mock response. The agent never reaches the provider.
  • Forced model routing and rate limiting -- Even if the agent requests a specific model (e.g., gpt-4o), the proxy may seamlessly rewrite the model field to use a different, operator-approved model (e.g., claude-3-haiku). The agent never knows its model was downgraded. Combined with rate limiting via 429 Too Many Requests responses, this enforces strict compute budgets across the fleet.

Provider Execution

The proxy strips the dummy token, attaches the real provider API key, and forwards the request upstream.

Inbound Interception (Provider to Agent)

After the provider responds but before the runner sees the result, the proxy can evaluate and amend:

  • Response amendment -- The proxy evaluates the provider's response against the enforce rules in the agent's contract and active policy modules. If the response violates the tone, instructions, or restrictions defined in the contract, the proxy rewrites the content before the agent sees it.
  • PII leakage blocking -- The proxy can detect and redact personally identifiable information. If the provider's response contains data that should not flow back to the agent (customer names, account numbers, internal identifiers), the proxy strips or masks it.
  • Drift scoring -- The proxy quantifies how far the provider's raw response drifted from the agent's ideal behavior as defined in its contract, emitting a structured log of the drift score. The scoring methodology is organization-specific and not defined by the cllama standard.

Egress

The (potentially amended) response is returned to the agent.

Passthrough vs Policy

The reference passthrough implementation currently performs identity resolution, model rewriting, and cost tracking only. It does not touch the messages array -- no prompt decoration, no response amendment. Full bidirectional interception is the cllama-policy proxy type, which is future work.

Context Mount Structure

The proxy needs to know who each agent is and what it is allowed to do. Clawdapus provides this through a shared context mount -- a directory tree with per-agent subdirectories containing the compiled contract and identity metadata.

Host-Side Layout

During claw up, Clawdapus generates context files under the runtime directory:

.claw-runtime/context/
├── crypto-crusher-0/
│   ├── AGENTS.md        # Compiled contract (includes, enforce, guide)
│   ├── CLAWDAPUS.md     # Infrastructure map (surfaces, skills, topology)
│   └── metadata.json    # Identity, bearer token, handles, policy modules
├── crypto-crusher-1/
│   ├── AGENTS.md
│   ├── CLAWDAPUS.md
│   └── metadata.json
└── analyst/
    ├── AGENTS.md
    ├── CLAWDAPUS.md
    └── metadata.json
FilePurpose
AGENTS.mdThe agent's compiled behavioral contract, including inlined enforce and guide content from INCLUDE directives.
CLAWDAPUS.mdInfrastructure context: surfaces, mount paths, peer handles, feeds, and available skills.
metadata.jsonMachine-readable identity (handles, allowed models, bearer token auth).

Container-Side Mount

The host directory is bind-mounted into the cllama container at /claw/context/<agent-id>/. The proxy reads CLAW_CONTEXT_ROOT (defaults to /claw/context) and loads each subdirectory as an agent identity.

The context/ directory segment is required in both host and container paths.

The context/ Segment Is Required

The mount path must include the context/ directory segment. The proxy expects CLAW_CONTEXT_ROOT to point at the directory containing agent subdirectories, not directly at an agent's files.

Context Mount Contents

The agentctx struct currently holds only three fields: AgentsMD, ClawdapusMD, and Metadata (used for bearer token auth). There are no outbound service credentials, no feed manifests, and no decoration config in the context mount today.

Scaled Services

For services with count > 1, context is generated per ordinal. A service named crypto-crusher with count: 3 produces three separate context directories: crypto-crusher-0/, crypto-crusher-1/, crypto-crusher-2/. Each ordinal gets its own bearer token, its own compiled contract, and its own audit trail.

The metadata.json file in each directory contains the bearer token secret used for authentication. The proxy validates incoming tokens against these metadata files to resolve caller identity.

Environment Variables

The cllama container receives its configuration through environment variables injected by claw up.

VariableDescription
CLAW_PODThe name of the pod (e.g., crypto-ops).
CLAW_CONTEXT_ROOTPath to the shared context mount root (defaults to /claw/context).
PROVIDER_API_KEY_*Real provider API keys -- OPENAI_API_KEY, ANTHROPIC_API_KEY, OPENROUTER_API_KEY, etc.

Where Provider Keys Go

Provider keys are configured in the pod YAML under x-claw.cllama-defaults.env. They are injected into the cllama proxy container only. They must not appear in regular agent environment: blocks.

yaml
x-claw:
  pod: my-fleet
  cllama-defaults:
    proxy: [passthrough]
    env:
      OPENROUTER_API_KEY: "${OPENROUTER_API_KEY}"
      ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"

cllama-env, Not environment

Provider API keys belong in x-claw.cllama-defaults.env (or service-level x-claw.cllama-env), never in the service's compose environment: block. Putting real keys in environment: defeats credential starvation -- the agent container would have direct provider access.

Pod Configuration

Declaring a cllama Proxy

The proxy is declared in claw-pod.yml via the cllama field on a service's x-claw block:

yaml
services:
  analyst:
    x-claw:
      agent: analyst
      cllama: passthrough
      cllama-env:
        OPENAI_API_KEY: ${OPENAI_API_KEY}
        ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}

The cllama value specifies the proxy type. Currently only passthrough ships as a reference implementation.

Provider Keys with YAML Anchors

For pods with multiple services using the same provider keys, use YAML anchors to stay DRY:

yaml
x-claw-env: &cllama-keys
  OPENAI_API_KEY: ${OPENAI_API_KEY}
  ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}

services:
  analyst:
    x-claw:
      agent: analyst
      cllama: passthrough
      cllama-env: *cllama-keys
  researcher:
    x-claw:
      agent: researcher
      cllama: passthrough
      cllama-env: *cllama-keys

Count Expansion with cllama

When a service declares both cllama and count > 1, each ordinal gets its own bearer token and context directory. The proxy authenticates each ordinal independently:

yaml
services:
  analyst:
    x-claw:
      agent: analyst
      cllama: passthrough
      count: 3

This produces analyst-0, analyst-1, and analyst-2, each with:

  • A unique bearer token in format analyst-N:<secret>
  • A context directory at /claw/context/analyst-N/
  • Independent telemetry tagged with claw_id: analyst-N

Cost Accounting

The proxy extracts token usage from every LLM response, multiplies by the pricing table, and tracks cost per agent, per provider, and per model. This gives operators real-time visibility into spend without relying on provider dashboards that aggregate across all API keys.

bash
$ claw ps

TENTACLE          STATUS    CLLAMA    DRIFT
crypto-crusher-0  running   healthy   0.02
crypto-crusher-1  running   healthy   0.04
crypto-crusher-2  running   WARNING   0.31

Telemetry and Audit

Every request through the proxy produces a structured JSON log entry on stdout. Clawdapus collects these for the claw audit command and for the Master Claw's fleet governance decisions.

Telemetry Fields

FieldDescription
timestampISO-8601 timestamp.
claw_idThe calling agent's identifier.
typeEvent type: request, response, error, intervention.
interventionWhy the proxy modified a prompt, dropped a tool, or amended a response. References the specific policy module or rule.
modelThe model used for the request.
tokens_inInput token count.
tokens_outOutput token count.
costEstimated cost for the request/response pair.
latencyRequest duration.

Every request/response pair produces two log events: one with type: "request" on ingress and one with type: "response" on egress. Error events use type: "error". Intervention events use type: "intervention". Token counts and cost estimates are extracted from the provider's response headers or body and attached to the response event.

Spec Divergences

The reference implementation has a few known divergences from the spec document:

  • The intervention field is typed as *string with no omitempty tag. Every event emits "intervention": null, even when no intervention occurred. This is intentional -- it ensures log parsers can rely on the field always being present.
  • The implementation emits four type values: request, response, error, and intervention. The spec (section 5) omits error from its type enum and lists drift_score instead.
  • The spec uses the field name intervention_reason where the reference logger uses intervention.

These divergences are documented here as practical guidance. The reference implementation is the source of truth for runtime behavior.

Structured, Not Self-Reported

Drift is independently scored from proxy telemetry -- not self-reported by the agent. The proxy provides a verifiable history of exactly what the bot tried to do versus what it was allowed to do.

Operator Dashboard

The cllama proxy serves a real-time web UI for operator visibility.

PropertyValue
Host port8181 (default)
Container port8081

The dashboard shows:

  • Live agent activity -- which agent is calling, which model, right now
  • Provider status and error rates
  • Cost breakdown per agent, per model, per time window
  • Token usage across the pod

The dashboard updates in real time as agents make LLM calls. No polling, no delay.

Ecosystem Implementations

Passthrough Reference

The reference image (ghcr.io/mostlydev/cllama) implements the v1 API contract as a pure transparent proxy:

  • Bearer-token identity resolution and validation.
  • Environment validation (CLAW_POD, CLAW_CONTEXT_ROOT, provider credentials).
  • OpenAI and Anthropic API format passthrough with format bridging.
  • Per-agent token usage and cost tracking.
  • Structured audit logging of all traffic.
  • Real-time operator dashboard.
  • No prompt decoration, no response amendment.

This image is used for testing and serves as the starting point for building custom policy engines.

Future: cllama-policy

The next planned implementation is cllama-policy, which adds bidirectional interception -- prompt decoration, tool scoping, response amendment, and drift scoring. The passthrough reference establishes the transport and identity contract; cllama-policy builds the governance logic on top.

Third-Party Engines

Any OpenAI-compatible proxy that consumes the Clawdapus context mount layout can act as a governance layer. The spec defines the contract, not the implementation. Operators can build proprietary engines incorporating advanced DLP, RAG-based context injection, or conversational configuration.

ClawRouter

ClawRouter is a specialized cllama implementation focused on forced model routing, rate limiting, and compute metering. It intercepts model requests, evaluates them against organizational budgets or provider availability, and dynamically routes, downgrades, or rate-limits requests to contain costs across a fleet of untrusted agents.

Security Model

Credential Isolation

The proxy enforces a strict credential boundary. Agent containers never see real provider API keys. The flow is:

  1. claw up generates a dummy bearer token for each agent.
  2. The agent's runner is configured with the proxy URL and dummy token.
  3. The proxy receives the dummy token, validates it, strips it, and attaches the real provider key.
  4. The agent cannot extract the real key because it only communicates with the proxy, never directly with the provider.

Network Isolation

Within the pod's Docker network, agents can reach the proxy at http://cllama-<type>:8080. They cannot reach the provider directly because no provider credentials exist in their environment. Even if an agent attempted to call the provider API directly, it would lack authentication.

Token Validation

Bearer tokens are validated against the principals field in each agent's metadata.json. A request with an invalid or missing token is rejected before any provider call is made. This is fail-closed: unknown tokens are denied, not passed through.

Implementation Notes

These notes reflect the current state of the reference implementation (cllama/ submodule) and are useful for debugging or extending.

Proxy Handler

The proxy handler (cllama/internal/proxy/handler.go) is pure passthrough. It rewrites the model field in the request body and forwards everything else unchanged. There is no prompt decoration, no system message injection, and no middleware hook system.

Logger Internals

The logger (cllama/internal/logging/logger.go) writes one JSON object per line to stdout. The intervention field is declared as *string (pointer to string) with no omitempty struct tag, so Go's JSON marshaler emits "intervention": null on every event. This is intentional -- it ensures log parsers can rely on the field always being present.

Image Resolution

When claw up encounters a cllama proxy declaration, it resolves the image through the standard ensureImage() fallback chain:

  1. Check if the image exists locally.
  2. Attempt docker pull from the registry.
  3. Attempt a local Dockerfile build.
  4. Attempt a git URL build.

For the public ghcr.io/mostlydev/cllama image, step 2 succeeds on most systems. The git URL fallback does not work for cllama because the Docker builder cannot access the private submodule repo.

Build and Publish

The cllama image supports multi-architecture builds:

bash
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t ghcr.io/mostlydev/cllama:latest \
  --push cllama/

The cllama/ directory is a git submodule pointing to a private SSH repo. Fresh clones leave it empty. The published image on ghcr.io is public, so end users pull the pre-built image rather than building from source.

Limitations

Current constraints to be aware of:

  • Single proxy type only. Multi-proxy is represented in the data model, but the runtime currently fails fast if more than one proxy type is declared per pod. Proxy chaining is a Phase 5 feature.
  • Passthrough only. The cllama-policy proxy type (full bidirectional interception with prompt decoration, tool scoping, and response amendment) is future work. The reference implementation does identity, routing, and cost tracking.
  • No per-turn hooks. The Clawdapus Driver interface has four methods (Validate, Materialize, PostApply, HealthProbe) -- all run once at deploy/startup. There is no per-turn or per-request hook. Any per-request context enrichment must go through cllama or a runner-native mechanism.
  • Intervention field quirk. The cllama logger emits "intervention": null on every event (the field has no omitempty tag). This is expected behavior, not a missing value.
  • Spec divergences. The specification uses intervention_reason and omits error from its type enum. The reference implementation uses intervention and emits error as a log type. Consumers should handle both.

See the full cllama specification on GitHub for the formal standard.

Released under the MIT License.