Metadata-Version: 2.4
Name: clawtex
Version: 1.1.3
Summary: Governed agent platform with MandelDB genetic memory. BB4C — Breath Before Code.
License: MIT
License-File: LICENSE
Keywords: ai,agent,governance,memory,llm,bb4c
Author: DeVere Cooley
Author-email: j@an2b.com
Requires-Python: >=3.11
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Provides-Extra: all
Provides-Extra: anthropic
Provides-Extra: dashboard
Provides-Extra: mcp
Provides-Extra: openai
Provides-Extra: slack
Provides-Extra: telegram
Requires-Dist: anthropic (>=0.34) ; extra == "anthropic" or extra == "all"
Requires-Dist: fastapi (>=0.110) ; extra == "dashboard" or extra == "all"
Requires-Dist: fastmcp (>=2.0) ; extra == "mcp" or extra == "all"
Requires-Dist: httpx (>=0.27)
Requires-Dist: jinja2 (>=3.1) ; extra == "dashboard" or extra == "all"
Requires-Dist: openai (>=1.45) ; extra == "openai" or extra == "all"
Requires-Dist: python-dotenv (>=1.0)
Requires-Dist: python-telegram-bot (>=20.0) ; extra == "telegram" or extra == "all"
Requires-Dist: pyyaml (>=6.0)
Requires-Dist: slack-bolt (>=1.18) ; extra == "slack" or extra == "all"
Requires-Dist: uvicorn (>=0.29) ; extra == "dashboard" or extra == "all"
Project-URL: Homepage, https://an2b.com
Project-URL: Repository, https://github.com/an2b-llc/clawtex
Description-Content-Type: text/markdown

# ClawTex

> *BB4C — Breath Before Code.*
> *Every action governed. Every thought remembered. Every agent intentional.*
>
> Built by [DeVere Cooley](https://an2b.com) · AN2B LLC

ClawTex is the product that should have shipped as OpenClaw — a complete, secure, memory-based agent. Governance first. Real memory, not markdown files.

---

## What Is It?

ClawTex is a production-ready AI agent platform built around four non-negotiable principles:

1. **Governance first** — The Warden policy engine gates every tool call before execution. No action happens without a breath.
2. **Real memory** — MandelDB provides semantic, vector-backed recall. Not flat files. Not conversation history. Genetic memory.
3. **Identity** — Every agent has a SOUL.md. Character is configuration.
4. **Composability** — Skills, channels, and tools are modular. Plug in Telegram, Slack, or build your own.

---

## Why?

Most agent frameworks give you:
- A chat loop
- Some tools
- Maybe a system prompt

That's not enough for production. Production agents need:
- **Policy enforcement** — you can't ship an agent that might delete emails or send unauthorized messages
- **Persistent memory** — users expect agents to remember context across sessions
- **Auditability** — you need to know what was blocked, approved, and why
- **Character** — a consistent identity that users can trust

ClawTex ships all of this out of the box.

---

## Quickstart

Three commands. That's it.

```bash
pip install clawtex

clawtex setup   # interactive wizard — configures everything

clawtex start   # your agent is live
```

The wizard handles your LLM key, MandelDB memory key, and channel tokens.
No manual `.env` editing. No guesswork.

---

## Getting Your Keys

You need 2 required keys and 1 optional channel token to get started.

### 🧠 MandelDB API Key (required — your agent's memory)

1. Go to **[mandeldb.com](https://mandeldb.com)**
2. Create a free account
3. Go to **API Keys** → **Create Bot Key**
4. Copy the key — it starts with `ek_bot_`

This gives your agent its own private memory namespace. Everything it learns lives here.

---

### 🤖 LLM Key — pick one:

**Anthropic (Claude) — recommended**
1. Go to **[console.anthropic.com](https://console.anthropic.com)**
2. Sign up / log in
3. Go to **API Keys** → **Create Key**
4. Copy the key — it starts with `sk-ant-`

**OpenAI (GPT-4)**
1. Go to **[platform.openai.com](https://platform.openai.com)**
2. Sign up / log in
3. Go to **API Keys** → **Create new secret key**
4. Copy the key — it starts with `sk-`

---

### 💬 Channel Token — pick one (or both):

**Telegram**
1. Open Telegram and search for **@BotFather**
2. Send `/newbot`
3. Follow the prompts — give your bot a name and username
4. BotFather gives you a token — it looks like `7812345678:AAH...`
5. Start a chat with your bot and send it a message before running ClawTex

**Slack**
1. Go to **[api.slack.com/apps](https://api.slack.com/apps)** → **Create New App** → **From Scratch**
2. Under **OAuth & Permissions**, add these Bot Token Scopes: `chat:write`, `im:write`, `channels:read`, `users:read`
3. Under **Socket Mode**, enable it and create an App-Level Token — this is your `SLACK_APP_TOKEN` (starts with `xapp-`)
4. Install the app to your workspace → copy the **Bot User OAuth Token** (starts with `xoxb-`)
5. Invite your bot to a channel: `/invite @yourbotname`

---

> **Minimum to get started:** MandelDB key + one LLM key. Channel tokens are optional — without one, ClawTex runs in CLI mode (great for testing).

---

## Architecture

```
┌───────────────────────────────────────────────────────────────┐
│                         ClawTex Agent                          │
│                                                                │
│  Channel                                                       │
│  ┌──────────┐                                                  │
│  │ Telegram │                                                  │
│  │  Slack   │──message──▶  handle_message()                    │
│  │   CLI    │                                                  │
│  │   MCP    │                                                  │
│  └──────────┘                                                  │
│                                                                │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                      Agent Core Loop                       │  │
│  │                                                            │  │
│  │  1. classify intent     (INSTANT / LIGHT / STANDARD /DEEP) │  │
│  │  2. recall memories     (MandelDB 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      │  │
│  │                                      │                     │  │
│  │                                      ├─ approved → execute │  │
│  │                                      └─ rejected → block   │  │
│  │  6. redact + ingest exchange  (MemoryContext)              │  │
│  └──────────────────────────────────────────────────────────┘  │
│                                                                │
│  ── Four governance layers ────────────────────────────────    │
│                                                                │
│  Warden              Tool registry       Skill manifests       │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐        │
│  │ policy.yaml  │   │  source-     │   │  declared_   │        │
│  │ rules +      │   │  tracked;    │   │  action_     │        │
│  │ when: ctx    │   │  TRUSTED_    │   │  types       │        │
│  │ NEVER_AUDIT  │   │  TOOL_       │   │  audit vs    │        │
│  │ _BYPASS      │   │  MODULES     │   │  registry    │        │
│  └──────────────┘   └──────────────┘   └──────────────┘        │
│                                                                │
│  Memory redactor (Layer 4)                                     │
│  ┌─────────────────────────────────────────────┐               │
│  │ scrubs API keys + PII before every ingest   │               │
│  │ sk-ant-… → [REDACTED:ANTHROPIC_KEY]         │               │
│  └─────────────────────────────────────────────┘               │
└───────────────────────────────────────────────────────────────┘
```

See [`docs/GOVERNANCE.md`](docs/GOVERNANCE.md) for the full layer-by-layer walkthrough.

---

## Configuration

All configuration lives in `.env` (see `.env.example`):

### 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 Claude model (default: `claude-3-5-sonnet-20241022`) |
| `OPENAI_MODEL` | No | Override OpenAI model (default: `gpt-4o`) |

### Memory

| Variable | Required | Description |
|----------|----------|-------------|
| `MEMORY_BACKEND` | No | `mandeldb` (default) or `pgvector` |
| `CLAWTEX_EIDETIC_URL` | Yes (MandelDB) | MandelDB base URL |
| `CLAWTEX_EIDETIC_KEY` | Yes (MandelDB) | `ek_bot_…` bot key |
| `CLAWTEX_EIDETIC_GCLOUD_ACCOUNT` | No | gcloud identity token path (Cloud Run) |
| `DREAM_INTERVAL_HOURS` | No | Memory consolidation interval (default: 6) |
| `CLAWTEX_REDACT_DISABLED` | No | `1` to turn off redaction (**debug only**) |
| `CLAWTEX_REDACT_PII` | No | `1` to also redact emails + long digit runs |
| `CLAWTEX_REDACT_EXTRA` | No | Additional regex for site-specific secret shapes |

Legacy `MANDELDB_URL` / `MANDELDB_API_KEY` are still accepted for backwards compatibility.

### Governance

| Variable | Required | Description |
|----------|----------|-------------|
| `WARDEN_POLICY` | No | Path to policy YAML (default: bundled `default.yaml`) |
| `WARDEN_MODE` | No | `enforce` (default) / `audit` / `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. Together they make "governed
agent" a defensible claim rather than a marketing line.

| Layer | What it does |
|---|---|
| **Warden** | Gates every tool call against a policy. ALLOW / REVIEW / DENY. |
| **Tool registry trust** | Rejects tools registered from untrusted Python modules. |
| **Skill manifests** | Audits that skills only drive their declared action_types. |
| **Memory redactor** | Scrubs secrets and optional PII before any memory ingest. |

**👉 Full walkthrough of every knob: [`docs/GOVERNANCE.md`](docs/GOVERNANCE.md)**

### Decisions & default policy

```yaml
# clawtex/governance/policies/default.yaml (v2)
version: 2
default: REVIEW   # unknown action_types pause before acting — BB4C default

rules:
  - action: "file.delete"
    decision: DENY
  - action: "email.delete"
    decision: REVIEW
  - action: "web.search"
    decision: ALLOW
  # …
```

`default: REVIEW` is the BB4C posture: anything the policy author didn't
anticipate should pause, not proceed. Deployments that prefer ALLOW-by-default
must set it explicitly.

### Context-aware conditions

Rules can gate on the tool call's arguments — path, URL host, recipient,
regex, etc.:

```yaml
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 doesn't
  - 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.

### Warden modes

| Mode | Behavior |
|---|---|
| `enforce` (default) | DENY blocks. REVIEW pauses for approval callback, else blocks. |
| `audit` | Log but allow — **except** `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 model, a malicious dependency could register `exec` under
`action_type="web.search"` and bypass Warden entirely. Fix:

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

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

Every production deployment should set this. `clawtex check` lists each
tool's `source` module and flags any that are untrusted.

### Memory redactor

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

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

# What lands in MandelDB / pgvector
"my key is [REDACTED:ANTHROPIC_KEY]"
```

Built-in shapes: Anthropic, OpenAI, MandelDB bot keys, GitHub tokens, AWS /
Google / Slack keys, JWTs, Bearer tokens, PEM blocks.

```bash
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 breathe() method

```python
# In agent.py — the philosophical core of ClawTex
async def breathe(self, tool: ToolDefinition, tool_input: dict) -> Decision:
    """Pause and consult the Warden before executing any tool call. BB4C."""
    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 authoritative "should I block?" answer —
it encodes mode + NEVER_AUDIT_BYPASS rules in one place so callers can't
drift.

---

## Memory

ClawTex runs on **two interchangeable memory backends** — pick per deployment.

| Backend | Use when | Set `MEMORY_BACKEND=` |
|---|---|---|
| **MandelDB** (default) | You want managed semantic memory + dream consolidation | `mandeldb` |
| **pgvector** | You're running your own Postgres (e.g. Supabase) and want schema isolation per tenant | `pgvector` |

Both present the same interface — `MemoryContext.build()` / `record_exchange()` / `ingest_fact()` — so switching backends is an env-var change, not a code change.

### How It Works

```python
# Before every response: recall what's relevant
memories = await memory.recall(query=user_message, top_k=5)

# After every exchange: remember what happened (redacted first)
await memory.record_exchange(user_message=msg, assistant_reply=reply)

# Periodically: consolidate memories (MandelDB only)
await memory.trigger_dream()
```

### Redaction before ingest

Every `user_message` and `assistant_reply` passes through `clawtex.memory.redactor` before being written. Built-in patterns scrub Anthropic / OpenAI / MandelDB / GitHub / AWS / Google / Slack keys, JWTs, Bearer tokens, and PEM blocks. Vector memory is forever; leaked secrets must never become recallable artifacts.

See the [Memory redactor](#memory-redactor) section above for config.

### 🧠 Brain Startup — Blackout Recovery

ClawTex agents auto-reconnect to their memory on every startup. If a session ends (crash, token limit, restart), the agent pulls recent context from the backend the moment it comes back online — no cold starts.

```python
agent = ClawTexAgent(name="MyAgent")
await agent.start()  # ← restores context from MandelDB, injects into system prompt
```

The startup context is injected before per-message recall, so the agent always knows:
- What it was working on last session
- Open threads and pending decisions
- Recent exchanges

**Fail-open** — if the memory backend is unreachable, the agent continues without startup context (degraded but functional). Never blocks startup.

### Getting a MandelDB Key

```bash
python scripts/register_bot.py --name MyAgent
```

This registers your agent with the MandelDB EngramPort API and writes your `ek_bot_` key to `.env`.

### Dream Scheduler

ClawTex runs a background dream scheduler that triggers MandelDB memory consolidation every `DREAM_INTERVAL_HOURS` (default: 6h). This compresses and clusters memories, improving recall quality over time.

---

## Skills (OpenClaw-compatible)

ClawTex uses the same `SKILL.md` format as OpenClaw — skills are fully interoperable between both frameworks, plus ClawTex adds optional governance declarations.

**👉 Full authoring guide: [`docs/SKILLS.md`](docs/SKILLS.md)**

### Installing Skills via clawhub

```bash
# Install the clawhub registry client (one-time)
npm install -g clawhub

# Install a skill
clawtex skill install weather
clawtex skill install github/issues

# Search for skills
clawtex skill search summarize

# List what's installed
clawtex skill list

# Update all skills
clawtex skill update

# Update a specific skill
clawtex skill update weather
```

### How Skills Work

At startup, ClawTex:
1. Scans `CLAWTEX_SKILLS_DIR` (default: `./skills`) for subdirectories with `SKILL.md`
2. Parses YAML frontmatter from each SKILL.md to extract name, description, version, tags
3. Injects an `<available_skills>` block into every system prompt

Per message, ClawTex:
1. Runs keyword matching against skill descriptions and tags
2. If a skill matches, injects its full SKILL.md content as `<active_skill>` in the prompt
3. The agent follows the skill's instructions for that response

### Writing a Skill (OpenClaw-compatible format)

```
skills/
└── my-skill/
    └── SKILL.md
```

`SKILL.md` with YAML frontmatter:
```markdown
---
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.

## Usage

...

---
*A ClawTex skill · BB4C · AN2B LLC*
```

The `description` and `tags` fields drive keyword matching. The `declared_action_types` field lets `clawtex check` audit that your skill only drives the action_types you declared — if the skill lists `tools: [exec]` but only declares `web.search`, the audit flags it. 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 | ✓ | ✓ (identical) |
| clawhub install | ✓ | ✓ |
| Skill injection | System prompt | System prompt |
| Per-message matching | Yes | Yes |
| `declared_action_types` audit | — | ✓ |
| MandelDB / pgvector memory | — | ✓ |
| Warden governance | — | ✓ |
| Tool registry trust model | — | ✓ |
| Secret/PII redaction | — | ✓ |

---

## Adding Tools

Tools are async Python functions registered with the tool registry:

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

@registry.register(
    name="my_tool",
    action_type="my.tool",      # must match 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. If you're shipping tools from a non-core package, add your module prefix to `CLAWTEX_TRUSTED_TOOL_MODULES`:

```bash
CLAWTEX_TRUSTED_TOOL_MODULES=clawtex.tools,my_company_tools
```

`clawtex check` will flag any tool registered from an untrusted source and fail the overall check. See [`docs/GOVERNANCE.md`](docs/GOVERNANCE.md#layer-2--tool-registry-trust-model) for the full threat model.

---

## Testing

```bash
# Run all tests
pytest tests/ -v

# Governance tests only (run these first — they're the critical path)
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 single one must return `DENY` or `REVIEW` — never `ALLOW`. If this test fails, do not deploy.

```python
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"  # This must never, ever fire.
```

---

## Docker

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

---

## License

MIT — see LICENSE.

---

## About

ClawTex is built by [DeVere Cooley](https://an2b.com) at **AN2B LLC** — an AI solutions company
building governed, production-ready AI infrastructure.

> *BB4C — Breath Before Code.*
> *Every action governed. Every thought remembered. Every agent intentional.*

---

*Forged by DeVere Cooley — BB4C — "Breath Before Code"*

