Skip to main content

Governed agent platform built on EngramPort GraphRAG memory. BB4C — Breath Before Code.

Project description

ClawTex

BB4C. Breath Before Code. Built by DeVere Cooley, AN2B LLC

ClawTex is a governed AI agent with a typed graph memory. It runs from one pip install, governs every tool call before it executes, and remembers across sessions in a real vector and graph store instead of flat files.

It is reactive: it answers messages. It is not an autonomous planner and does not decompose goals on its own.


What it is

ClawTex is an agent runtime built around three things that are wired into the code, not the pitch:

  1. Governance on every tool call. The Warden policy engine evaluates each tool call and returns ALLOW, DENY, or REVIEW before the call runs.
  2. Typed graph memory. Memory lives in EngramPort, a vector and graph store. Exchanges are recalled before each response and ingested after. Durable lessons and synthesized observations are written as typed graph nodes (principle, insight) so grooming and consolidation run over a connected graph.
  3. Bring your own LLM. Anthropic ships in the box. OpenAI and OpenAI-compatible endpoints are an optional extra.

You provide a SOUL.md to set the agent's identity. If you don't, a default persona is used.


Why

Most agent starter kits give you a chat loop, some tools, and a system prompt. That leaves three gaps ClawTex closes in code:

  • Policy enforcement. You should be able to stop an agent from deleting a file or sending an unauthorized message. Warden gates each tool call.
  • Persistent memory. The agent recalls prior context before answering and records the exchange after. Memory is typed and graph-linked, not a log file.
  • An audit trail. DENY and REVIEW decisions are written to a JSONL audit log so you can see what was blocked and why.

Quickstart

pip install clawtex

Claude works out of the box. The Anthropic SDK ships as a core dependency, so a bare pip install clawtex is enough to run with an Anthropic key.

1. See it work, zero keys, no signup:

clawtex demo

clawtex demo runs entirely on your machine with a mock LLM and an in-memory store. It shows three things: the agent responds to a prompt, the real Warden denies a dangerous action (file.delete) before it runs, and a seeded fact is recalled. No API key, no network. (Tested in tests/test_demo.py.)

2. Wire the real thing:

clawtex init    # interactive wizard: LLM key, EngramPort key, channels
clawtex start   # start your governed agent (CLI by default)

clawtex init writes a .clawtex.toml, writes a .env for compatibility, and copies a starter SOUL.md plus a starter skill into your working directory. The runtime reads .clawtex.toml automatically on startup.

The wizard asks you to paste an EngramPort key. It does not auto-provision a brain for you. You mint the key at the dashboard (see below) and paste it in. You can press Enter to skip and add it later; the agent then runs without persistent memory until you do.

3. Confirm your config:

clawtex check

clawtex check reports your Warden policy, whether your keys are set, loaded skills, registered tools and their source modules, and any skill manifest violations. It exits non-zero if a tool comes from an untrusted source or a skill manifest is inconsistent, so you can use it in CI.


Getting your keys

You need two keys to go live: an LLM key and an EngramPort memory key. Channel tokens are optional. To try first without either, run clawtex demo.

EngramPort API key (your agent's memory)

  1. Go to engramport.com.
  2. Sign up and create a brain. There is a free tier; check the dashboard for current limits.
  3. Copy the key. It starts with ek_live_.

This gives your agent a namespace-isolated memory on the EngramPort API (https://api.engramport.com). EngramPort is also usable standalone over the same API and MCP server; ClawTex is one way to drive it.

LLM key, pick one

Anthropic (Claude), recommended

  1. Go to console.anthropic.com.
  2. Create an API key under API Keys.
  3. Copy it. It starts with sk-ant-.

OpenAI

  1. Go to platform.openai.com.
  2. Create a secret key under API Keys.
  3. Copy it. It starts with sk-.

OpenAI support is an optional extra: pip install 'clawtex[openai]'.

Channel token, optional, pick one or both

Telegram

  1. Open Telegram, message @BotFather, send /newbot.
  2. Follow the prompts to name your bot.
  3. Copy the token (looks like 7812345678:AAH...).
  4. Message your bot once before starting ClawTex.

Slack

  1. Go to api.slack.com/apps, create an app from scratch.
  2. Under OAuth & Permissions, add bot scopes: chat:write, im:write, channels:read, users:read.
  3. Under Socket Mode, enable it and create an app-level token (SLACK_APP_TOKEN, starts with xapp-).
  4. Install the app and copy the Bot User OAuth Token (xoxb-).
  5. Invite the bot to a channel.

Minimum to go live: an EngramPort key (ek_live_…) plus one LLM key. Without a channel token, ClawTex runs in CLI mode. Or skip keys entirely and run clawtex demo.


Architecture

┌───────────────────────────────────────────────────────────────┐
│                         ClawTex Agent                          │
│                                                                │
│  Channel                                                       │
│  ┌──────────┐                                                  │
│  │ Telegram │                                                  │
│  │  Slack   │──message──▶  handle_message()                    │
│  │   CLI    │                                                  │
│  └──────────┘                                                  │
│                                                                │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                  Agent loop (per message)                  │  │
│  │                                                            │  │
│  │  1. classify intent     (INSTANT / LIGHT / STANDARD/DEEP) │  │
│  │  2. recall memories     (EngramPort or pgvector)           │  │
│  │  3. build prompt        (SOUL.md + memory + skills)        │  │
│  │  4. call LLM            (Anthropic / OpenAI)               │  │
│  │  5. for each tool call:                                    │  │
│  │        breathe()  ─▶  Warden.check_async(ctx)              │  │
│  │                       ├─ ALLOW  ─▶  execute                │  │
│  │                       ├─ DENY   ─▶  BlockedByWarden        │  │
│  │                       └─ REVIEW ─▶  approval callback,     │  │
│  │                                     else block             │  │
│  │  6. redact + ingest the exchange  (MemoryContext)          │  │
│  └──────────────────────────────────────────────────────────┘  │
│                                                                │
│  Four governance layers (see docs/GOVERNANCE.md):              │
│    Warden · tool registry trust · skill manifests · redactor  │
└───────────────────────────────────────────────────────────────┘

EngramPort is also exposed as a standalone MCP server for editors like Claude Code, started with python -m clawtex.mcp (requires pip install 'clawtex[mcp]'). That is a separate entry point, not a chat channel in the agent loop above.

See docs/GOVERNANCE.md for the layer-by-layer walkthrough.


Configuration

clawtex init writes a .clawtex.toml, and the runtime loads it automatically at startup. Precedence is real environment variables > ./.clawtex.toml > ~/.clawtex.toml > defaults. You can also set any variable below directly in the environment or a .env file; they map 1:1 onto the TOML keys.

Core

Variable Required Description
CLAWTEX_NAME Yes Agent name / memory namespace
CLAWTEX_SOUL No Path to SOUL.md (default: ./SOUL.md)
LLM_PROVIDER Yes anthropic or openai
ANTHROPIC_API_KEY If anthropic Your Anthropic API key
OPENAI_API_KEY If openai Your OpenAI API key
ANTHROPIC_MODEL No Override the Claude model (default: claude-sonnet-4-5-20250929)
OPENAI_MODEL No Override the OpenAI model (default: gpt-4o)

Per-tier Anthropic overrides (ANTHROPIC_MODEL_LIGHT, _STANDARD, _DEEP) are also read if set.

Memory

Variable Required Description
MEMORY_BACKEND No engramport (default) or pgvector
CLAWTEX_ENGRAMPORT_URL No EngramPort base URL (default: https://api.engramport.com)
CLAWTEX_ENGRAMPORT_KEY Yes (EngramPort) Your EngramPort API key (ek_live_…)
CLAWTEX_ENGRAMPORT_GCLOUD_ACCOUNT No gcloud identity token path (self-hosted Cloud Run)
DREAM_INTERVAL_HOURS No Memory maintenance interval (default: 6)
CLAWTEX_REDACT_DISABLED No 1 to turn off redaction (debug only)
CLAWTEX_REDACT_PII No 1 to also redact emails and long digit runs
CLAWTEX_REDACT_EXTRA No Additional regex for your own secret shapes

The older CLAWTEX_EIDETIC_* names are still accepted as legacy aliases.

Governance

Variable Required Description
WARDEN_POLICY No Path to a policy YAML (default: bundled default.yaml)
WARDEN_MODE No enforce (default), audit, or strict
CLAWTEX_TRUSTED_TOOL_MODULES No Module prefixes allowed to register tools. Prefix with strict: to hard-reject others. Set this in prod.

Channels

Variable Required Description
TELEGRAM_BOT_TOKEN Optional Telegram bot token
SLACK_BOT_TOKEN Optional Slack bot token
SLACK_APP_TOKEN Optional Slack app-level token (Socket Mode)

Governance

Governance in ClawTex is four independent layers, not one policy engine. Each layer closes a different class of failure.

Layer What it does
Warden Evaluates every tool call against a policy. ALLOW / REVIEW / DENY.
Tool registry trust Flags or rejects tools registered from untrusted Python modules.
Skill manifests Audits that skills only drive their declared action_types.
Memory redactor Scrubs known secret shapes and optional PII before any memory ingest.

Full walkthrough of every knob: docs/GOVERNANCE.md

The bundled default policy

The policy that ships in clawtex/governance/policies/default.yaml:

version: 2
default: REVIEW   # unmatched action_types pause before acting

rules:
  - action: "file.delete"
    decision: DENY
  - action: "exec"
    decision: REVIEW
  - action: "email.delete"
    decision: REVIEW
  - action: "email.send"
    decision: REVIEW
  - action: "http.post"
    decision: REVIEW
  - action: "web.search"
    decision: ALLOW
  - action: "file.read"
    decision: ALLOW
  - action: "http.get"
    decision: ALLOW
  # see the file for the full list

default: REVIEW is the BB4C posture: anything the policy author didn't anticipate pauses rather than proceeds. A deployment that wants ALLOW-by-default must set it explicitly. The bundled policy denies file.delete and reviews exec; if you want hard denies for db.drop / db.truncate, add them in your own policy file (there is a starter in docs/GOVERNANCE.md).

Context-aware conditions

Rules can gate on the tool call's arguments (path, URL host, recipient, regex):

rules:
  - action: "file.write"
    decision: ALLOW
    when:
      input.path:
        glob: ["/tmp/**", "./workspace/**"]
  - action: "file.write"
    decision: REVIEW

  - action: "http.post"
    decision: ALLOW
    when:
      input.url:
        host_suffix: ["an2b.com"]   # api.an2b.com passes, evilan2b.com does not
  - action: "http.post"
    decision: REVIEW

Operators: equals, not_equals, in, not_in, glob, regex, host_in, host_suffix. Multiple operators in one when AND together. An unknown operator fails closed (the rule does not match).

Warden modes

Mode Behavior
enforce (default) DENY blocks. REVIEW pauses for the approval callback, or blocks if none is set.
audit Log but allow, except exec, exec.*, file.delete, email.delete, db.drop, db.truncate, which always enforce (NEVER_AUDIT_BYPASS).
strict REVIEW is treated as DENY (no human in the loop).

Tool registry trust (CLAWTEX_TRUSTED_TOOL_MODULES)

Any Python package that imports clawtex.tools.registry can register a tool. Without a trust setting, a dependency could register exec under action_type="web.search" and get past Warden. Set the allowed module prefixes:

# Permissive: warn on untrusted sources (dev)
CLAWTEX_TRUSTED_TOOL_MODULES=clawtex.tools,my_company_tools

# Hard-reject untrusted sources at registration time (prod)
CLAWTEX_TRUSTED_TOOL_MODULES=strict:clawtex.tools,my_company_tools

clawtex check lists each tool's source module and flags untrusted ones.

Memory redactor

Vector memory is durable. A user pasting an API key should not become a permanent, recallable artifact. clawtex.memory.redactor runs over every exchange before ingest:

# Input
"my key is sk-ant-AAAABBBBCCCCDDDDEEEEFFFF1234"

# What is written to memory
"my key is [REDACTED:ANTHROPIC_KEY]"

Built-in shapes: Anthropic, OpenAI, EngramPort keys (ek_live_ / ek_test_ / ek_bot_), GitHub tokens, AWS access and secret keys, Google API keys, Slack tokens, JWTs, Bearer tokens, and PEM blocks.

CLAWTEX_REDACT_PII=1                    # also scrub emails + long digit runs
CLAWTEX_REDACT_EXTRA=INT-[A-Z0-9]{8}    # your own secret shapes
CLAWTEX_REDACT_DISABLED=1               # debug only, do not set in prod

The redactor matches the secret shapes listed above. It does not redact arbitrary file paths or free-form sensitive content, so do not point the agent at sensitive or regulated data and assume redaction will catch it.

The breathe() method

# clawtex/agent.py
async def breathe(self, tool: ToolDefinition, tool_input: dict) -> Decision:
    """Pause and consult the Warden before executing any tool call. BB4C."""
    context = {"tool": tool.name, "input": tool_input, "agent": self.name}
    decision = await self.warden.check_async(tool.action_type, context)
    if self.warden.enforce_decision(tool.action_type, decision):
        raise BlockedByWarden(tool.action_type, tool.name)
    return decision

warden.enforce_decision() is the single "should I block?" answer. It encodes mode and NEVER_AUDIT_BYPASS in one place so callers can't drift.


Memory

ClawTex runs on two interchangeable memory backends. Pick one per deployment.

Backend Use when Set MEMORY_BACKEND=
EngramPort (default) You want managed vector + graph memory with grooming and consolidation engramport
pgvector You run your own Postgres (e.g. Supabase) and want schema isolation per tenant pgvector

Both present the same MemoryContext interface (build(), record_exchange(), ingest_fact()), so switching backends is an env-var change, not a code change. The typed-write and graph filter features (typed nodes, dedup keys, recall filters) are supported on EngramPort; on pgvector they degrade gracefully to no-ops rather than erroring.

How it works

# Before each response: recall what is relevant
context = await memory.build(query=user_message)

# After each exchange: record it (redacted first)
await memory.record_exchange(user_message=msg, assistant_reply=reply)

# Periodically: groom then consolidate (EngramPort)
await memory.trigger_groom()
await memory.trigger_dream()

Typed graph memory

Raw exchanges are stored as memory nodes. Two typed writes give the graph higher-signal material:

  • ingest_principle() stores a durable lesson or rule as a principle node.
  • ingest_insight() stores a synthesized observation as an insight node.

A dedup_key makes a write idempotent: re-ingesting the same key updates the node in place instead of piling up duplicates. Identity is namespace + dedup_key. record_user_profile() uses this to keep one profile row per user.

Recall can be filtered by node type, similarity floor, source tag, date window, and whether to include graph-linked neighbours. The intent router drives these per turn so deep analysis pulls a wider, graph-linked slice while cheap turns stay tight.

Redaction before ingest

Every user_message and assistant_reply passes through the redactor before being written. See the Memory redactor section for the shapes it covers and its limits.

Startup recall

agent.start() recalls recent context from the backend and injects it into the system prompt before the first message is handled, so a restarted agent comes up with its prior context instead of a blank slate.

agent = ClawTexAgent(name="MyAgent")
await agent.start()  # recalls recent context, injects it into the system prompt

This is fail-open: if the backend is unreachable, the agent continues without startup context rather than blocking startup.

Memory maintenance

ClawTex runs a background loop every DREAM_INTERVAL_HOURS (default 6) that grooms (auto-links related memories) and then consolidates (synthesizes higher-order insights) on the EngramPort backend. Each step is best-effort and non-fatal: a maintenance failure never takes down the request path.


Skills (OpenClaw-compatible)

ClawTex uses the same SKILL.md format as OpenClaw, and adds an optional governance declaration (declared_action_types).

Full authoring guide: docs/SKILLS.md

Installing skills via clawhub

Skill install and search are a thin wrapper around the clawhub CLI. Install it first:

npm install -g clawhub

clawtex skill install weather
clawtex skill install github/issues
clawtex skill search summarize
clawtex skill list
clawtex skill update            # all skills
clawtex skill update weather    # one skill

clawtex skill list works without clawhub (it scans your skills directory). install, search, and update require the clawhub binary on your PATH and fail with a clear message if it is missing.

How skills work

At startup, ClawTex scans CLAWTEX_SKILLS_DIR (default ./skills) recursively for SKILL.md files, parses their YAML frontmatter, and injects an <available_skills> block into the system prompt.

Per message, it runs keyword overlap between the message and each skill's description, tags, and name. If a skill matches, its full SKILL.md body is injected as <active_skill>. The LLM then decides which tools to call, and each tool call is gated by the Warden as usual. Skills are prompt-level: they do not register tools or grant tool access.

Writing a skill

skills/
└── my-skill/
    └── SKILL.md
---
name: my-skill
display_name: My Skill
description: What this skill does in one line.
version: 1.0.0
tags: [keyword1, keyword2]
tools: [web_search, file_read]
declared_action_types: [web.search, file.read]
---

## Instructions

Describe what the agent should do when this skill is active.

---
A ClawTex skill · BB4C · AN2B LLC

description and tags drive keyword matching. declared_action_types lets clawtex check audit that the skill's referenced tools only drive the action_types you declared. If a skill lists tools: [exec] but declares only web.search, the audit flags it. The check is opt-in: skills without the field are skipped. Glob patterns like file.* are supported.

ClawTex vs OpenClaw, skill differences

Feature OpenClaw ClawTex
SKILL.md format yes yes (identical)
clawhub install yes yes
Skill injection system prompt system prompt
Per-message matching yes yes
declared_action_types audit no yes
EngramPort / pgvector memory no yes
Warden governance no yes
Tool registry trust model no yes
Secret/PII redaction no yes

Adding tools

Tools are async Python functions registered with the tool registry:

# my_company_tools/my_tool.py
from clawtex.tools.registry import registry

@registry.register(
    name="my_tool",
    action_type="my.tool",      # must map to a Warden policy rule
    description="Does something useful.",
    parameters={...},           # JSON Schema
)
async def my_tool(param1: str, **_) -> dict:
    return {"result": "..."}

Trust model

Every registered tool captures its source module via call-stack inspection. If you ship tools from a non-core package, add its module prefix to CLAWTEX_TRUSTED_TOOL_MODULES:

CLAWTEX_TRUSTED_TOOL_MODULES=clawtex.tools,my_company_tools

clawtex check flags any tool registered from an untrusted source and exits non-zero. See docs/GOVERNANCE.md for the full threat model.


Testing

pytest tests/ -v

# Governance tests
pytest tests/test_governance.py -v

# With coverage
pytest tests/ --cov=clawtex --cov-report=term-missing

The meta inbox test

The signature governance test simulates 200 email deletion requests. Every one must return DENY or REVIEW, never ALLOW.

def test_200_email_deletes_never_allow(self) -> None:
    warden = make_warden()
    for i in range(200):
        decision = warden.check("email.delete", {"email_id": f"msg_{i:04d}"})
        assert decision != "ALLOW"

Docker

docker-compose up -d
docker-compose logs -f clawtex

License

MIT. See LICENSE.


About

ClawTex is built by DeVere Cooley at AN2B LLC.

BB4C. Breath Before Code.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clawtex-3.1.0.tar.gz (135.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clawtex-3.1.0-py3-none-any.whl (150.2 kB view details)

Uploaded Python 3

File details

Details for the file clawtex-3.1.0.tar.gz.

File metadata

  • Download URL: clawtex-3.1.0.tar.gz
  • Upload date:
  • Size: 135.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for clawtex-3.1.0.tar.gz
Algorithm Hash digest
SHA256 93e42303613855e262fd58e4a1f8b8259accd5c6675a567a0c7ae8363e127f37
MD5 cd4727f098c2692fe64b62c668d130c4
BLAKE2b-256 f1502262f9d1292957179671c6965e881cfb6af7439c55ca8440775f7ec23cd1

See more details on using hashes here.

Provenance

The following attestation bundles were made for clawtex-3.1.0.tar.gz:

Publisher: publish.yml on jcools1977/clawtex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file clawtex-3.1.0-py3-none-any.whl.

File metadata

  • Download URL: clawtex-3.1.0-py3-none-any.whl
  • Upload date:
  • Size: 150.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for clawtex-3.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 759b40380aa2d3d710846c31009f0464b8cdce097d43d5954f125381023c0f10
MD5 35292f0855eda0c4e975a38f5c85927c
BLAKE2b-256 da7a75b92ec25355f160ab4a8eda8f205ea8f31649b518ea021e0cc991d3bd06

See more details on using hashes here.

Provenance

The following attestation bundles were made for clawtex-3.1.0-py3-none-any.whl:

Publisher: publish.yml on jcools1977/clawtex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page