proxagent 0.1.0
Supabase-backed config, logging, and memory for Claude Agent SDK agents
Requires Python: >=3.12

# proxagent

Supabase-backed config, logging, and memory for Claude Agent SDK agents.

One Supabase project = one company. One company can have many agents. All tables are scoped by agent, identified by a human-readable slug (e.g. `otmc-agent`, `claims-agent`).

## Install

```bash
uv pip install -e .
```

## Setup

### 1. Get a Personal Access Token

Go to **Supabase Dashboard > Account (top right) > Access Tokens** and create a PAT.

### 2. Check and create tables

```bash
uv run proxagent check
```

The CLI will:
- Ask for your PAT
- List your Supabase projects (arrow-key select)
- Check if all `_proxagent_*` tables exist
- Offer to create them if missing

Tables are prefixed with `_proxagent_` to avoid collisions. RLS is enabled by default.

### 3. Register an agent

Insert a row into `_proxagent_agents`:

```sql
insert into _proxagent_agents (slug, name)
values ('my-agent', 'My Agent');
```

### 4. Add skills

Insert rows into `_proxagent_skills`:

```sql
insert into _proxagent_skills (agent_id, name, description, content)
values (
  (select id from _proxagent_agents where slug = 'my-agent'),
  'greeting_style',
  'How to greet users',
  '# Greeting Style\n\nAlways greet users warmly...'
);
```

## Python API

### ProxAgent

Single object for config, skills, and logging.

```python
from proxagent import ProxAgent

agent = ProxAgent("my-agent", supabase_url="...", supabase_key="...")
agent.fetch()
```

**Build system prompt** (fills placeholders like `{issue_key}`):

```python
prompt = agent.build_prompt(issue_key="COPS-123")
```

**Write skills to disk** (creates `.claude/skills/{name}/SKILL.md` with YAML frontmatter):

```python
agent.write_skills(".")  # writes to ./.claude/skills/*/SKILL.md
```

**Get skills as data** (for writing into E2B sandboxes or other targets):

```python
for skill in agent.skills_files():
    # skill["path"]    -> "greeting_style/SKILL.md"
    # skill["content"] -> "---\nname: greeting_style\n..."
    sandbox.files.write(f"/app/.claude/skills/{skill['path']}", skill['content'])
```

**Write memories to CLAUDE.md** (each memory becomes a bullet point):

```python
agent.write_claude_md(".")  # writes to ./CLAUDE.md
```

**Get CLAUDE.md content as string** (for writing into E2B sandboxes):

```python
content = agent.claude_md_content()
sandbox.files.write("/app/CLAUDE.md", content)
```

**Save a new memory** (persists to `_proxagent_memories`):

```python
agent.save_memory(
    learning="For noissue.co WRO tickets, use orderops@noissue.co",
    context="Taught by Nipun on COPS-198277"
)
```

### Memory MCP Server

Create an MCP server with a `save_learning` tool that the agent can call at runtime to persist new learnings:

```python
from proxagent import ProxAgent, create_memory_server

agent = ProxAgent("my-agent", ...).fetch()
memory_server = create_memory_server(agent)

options = ClaudeAgentOptions(
    mcp_servers={"memory": memory_server},
    allowed_tools=["mcp__memory__save_learning"],
)
```

The agent sees a `save_learning` tool that accepts `learning` (str) and `context` (str). Writes to `_proxagent_memories` under the hood.

**Log SDK messages** to `_proxagent_runs` and `_proxagent_logs`:

```python
agent.start_run(run_label="COPS-123", sandbox_id="sbx_abc")

async for message in client.receive_response():
    agent.log(message)
```

The logger handles all message types automatically:
- **SystemMessage** (init) → creates a run in `_proxagent_runs`
- **AssistantMessage** → logs each block (text, thinking, tool use, tool result)
- **UserMessage** → logs user input and tool results
- **ResultMessage** → finalizes the run with cost, duration, tokens

### Environment variables

| Variable | Description |
|----------|-------------|
| `SUPABASE_URL` | Supabase project URL (e.g. `https://abc123.supabase.co`) |
| `SUPABASE_SERVICE_ROLE_KEY` | Service role key or new-style secret key (`sb_secret_...`) |
| `SUPABASE_ACCESS_TOKEN` | Personal Access Token (for CLI only) |

`ProxAgent` reads from `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY` by default, or accepts them as constructor args.

## Tables

All tables use the `_proxagent_` prefix and have RLS enabled.

| Table | Purpose |
|-------|---------|
| `_proxagent_agents` | Agent registry — slug, name, system_prompt |
| `_proxagent_skills` | Skills per agent — name, description, content, is_active |
| `_proxagent_memories` | Learnings per agent — learning, context, is_active |
| `_proxagent_runs` | One row per agent execution — cost, duration, tokens, result |
| `_proxagent_logs` | Message-level detail — tool calls, text, thinking blocks |

## CLI

```bash
proxagent check    # Check/create tables in your Supabase project
```