# The Meta-Agent — Governance Through Conversation

The meta-agent is Powerloom's AI-native admin interface. An Opus-powered agent that sits inside the control plane and provisions governed agent fleets on your behalf — from a plain-English conversation.

Everything it does, you could do with the CLI or the API. The meta-agent does it in 60 seconds, in dependency order, fully governed, fully audited. You talk. It provisions.

---

## What It Is

The meta-agent is a Claude Managed Agent (CMA) running on Opus. Its single MCP server wraps the Powerloom REST API — 11 tools that cover reading, creating, and wiring resources across your organization.

It's not a service account. It's not a backdoor. Every action the meta-agent takes is gated by **your** RBAC permissions. If you can't create an agent in `/acme/production` with your own credentials, the meta-agent can't either. It's a delegate, not an escalation path.

---

## How It Works

```
You send a prompt
    ↓
Meta-agent receives it via CMA session
    ↓
Meta-agent calls Powerloom API tools (list, create, attach)
    ↓
Each tool call mints a 5-minute JWT scoped to YOUR identity
    ↓
API enforces YOUR RBAC on every call
    ↓
Resources are created, wired, and recorded in the audit trail
    ↓
Meta-agent summarizes what it did
```

The session-delegated JWT is the key mechanism. When the meta-agent calls a tool, the MCP handler requests a short-lived token from the control plane, bound to the CMA session you started. That token carries your user ID, your organization, and your permissions. The API doesn't know or care that the request came from the meta-agent — it evaluates RBAC against your identity.

5-minute token TTL. Re-fetched on every tool call. No standing privilege.

---

## What It Can Do

The meta-agent has 11 tools. Five read the current state. Two look up individual resources. Four create and wire things.

### Read tools

| Tool | Returns |
|---|---|
| `list_ous` | Your OU hierarchy as a nested tree |
| `list_users` | All users in your organization |
| `list_skills` | All skills with version info |
| `list_mcp_servers` | All MCP server registrations |
| `list_agents` | All agents with sync status |

### Lookup tools

| Tool | Input | Returns |
|---|---|---|
| `describe_user` | email address | Full user detail including principal ID and home OU |
| `describe_agent` | agent UUID | Full agent detail including attachments and CMA sync state |

### Mutation tools

| Tool | What it does |
|---|---|
| `create_agent` | Creates an agent in a specified OU with model, prompt, and owner |
| `attach_skill_to_agent` | Wires a skill to an agent |
| `attach_mcp_server_to_agent` | Wires an MCP server registration to an agent |
| `create_credential` | Mints a bearer token for an agent-to-MCP-server binding |

That's the full surface. The meta-agent can't modify approval policies, can't access other organizations, can't touch the super-admin console, and can't do anything the 11 tools don't cover. The boundary is explicit.

---

## Using the Meta-Agent

### Starting a session

Invoke the meta-agent the same way you'd invoke any agent — via the API or the console.

**From the console:** Navigate to the meta-agent in your Agents list and open a session. Type your request.

**From the API:**

```bash
curl -X POST https://api.powerloom.org/agents/$META_AGENT_ID/invoke \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "prompt": "Set up a code review agent for the engineering team.",
    "mode": "fire_and_forget"
  }'
```

Connect to the returned WebSocket URL to stream the conversation.

### How to talk to it

The meta-agent is an IT operator co-pilot. It works best when you state what you want and let it figure out the dependency order.

**Be specific about what you need:**

> "Create a PostgreSQL analysis agent for the platform team. It should use the pg-analytics MCP server and the sql-review skill. Owner is admin@acme.com."

The meta-agent will:
1. Look up the user by email to get their principal ID
2. Look up the OU for the platform team
3. Check that the MCP server and skill exist
4. Create the agent
5. Attach the skill
6. Attach the MCP server
7. Mint the credential
8. Report back with the agent ID

**Be clear about scope when it matters:**

> "Provision this in /acme/engineering/platform, not the root OU."

The meta-agent respects OU paths. If you don't specify, it'll ask.

**Ask it to check before acting:**

> "What agents and MCP servers already exist in the engineering OU?"

It'll call the read tools and give you an inventory before creating anything.

### What a session looks like

Here's a real interaction pattern:

**You:**
> "Set up a scoped sales-prospecting agent for Emma on the sales team with Apollo and Gmail access."

**Meta-agent:**
> Let me check the current state.
>
> *[calls list_ous]* — Found `/acme/sales`
> *[calls describe_user with emma@acme.com]* — Emma is in `/acme/sales`, principal ID `e5f6...`
> *[calls list_mcp_servers]* — Found `apollo-mcp` and `gmail-mcp` in `/acme/sales`
> *[calls list_skills]* — Found `web-search` skill
>
> I'll create the agent in `/acme/sales` owned by Emma, then wire the MCP servers and mint credentials.
>
> *[calls create_agent]* — Agent `sales-prospector` created, ID `a1b2...`
> *[calls attach_mcp_server_to_agent × 2]* — Apollo and Gmail attached
> *[calls attach_skill_to_agent]* — web-search attached
> *[calls create_credential × 2]* — Bearer tokens minted for both MCP servers
>
> Done. Agent `sales-prospector` created in `/acme/sales`:
> - Model: claude-sonnet-4-6
> - Owner: emma@acme.com
> - MCP servers: apollo-mcp, gmail-mcp
> - Skills: web-search
> - Credentials: minted
>
> The reconciler will push this to CMA within a few seconds. You can invoke it at `POST /agents/a1b2.../invoke`.

Every tool call in that sequence is RBAC-checked against your identity, executed through your permissions, and recorded in the audit trail.

---

## When It Can't Help

The meta-agent surfaces errors directly. If something fails, you see the raw error — no sugar-coating.

**Permission denied:**

> API returned 403: insufficient permissions. You need `agent:create` on `/acme/production` to create an agent there. Ask an OrgAdmin to grant a binding, or create the agent in an OU where you have access.

**Approval required:**

If an approval policy matches the mutation, the meta-agent gets a 202 instead of a 201. It'll tell you:

> Agent creation in `/acme/production` requires approval. Request submitted (ID: `req_c3d4...`). Your OrgAdmin will see it in the `/approvals` inbox. The agent will be created once approved.

The meta-agent can't approve its own requests. The approval gate applies regardless of whether the mutation came from a human, the CLI, or the meta-agent.

**Resource not found:**

> No user found with email `jane@typo.com`. Check the email address and try again.

**Reconciler not finished:**

> Agent created but `cma_agent_id` is null — the reconciler hasn't pushed it to Anthropic yet. Wait a few seconds and invoke. If it persists, check sync state for errors.

---

## Security Model

The meta-agent's security posture rests on three guarantees:

### No privilege escalation

The session-delegated JWT carries your identity. The API evaluates RBAC against your user, not against the meta-agent. A prompt injection that tries to escalate privileges hits the same RBAC wall as a malicious API call — the token's `sub` claim can't be changed by the agent.

### No standing access

Tokens are minted per tool call with a 5-minute TTL. There's no long-lived service credential. If the session ends, the tokens expire. If you revoke your own access, the next tool call fails.

### Full audit trail

Every mutation the meta-agent makes writes to the `control_plane_audit` table — append-only, SHA-256 hash-chained, tamper-evident. Each entry carries the `delegated_from_session` field linking it to the CMA session you started. The audit chain doesn't distinguish between human-initiated and meta-agent-initiated actions — both are first-class entries, both traceable to the authenticated admin.

---

## Setup

The meta-agent is bootstrapped once per organization. Your Powerloom admin runs the bootstrap script, which:

1. Deploys the `powerloom_meta` MCP server (shared fleet, sub-30s)
2. Creates the meta-agent (Opus-powered, `user` kind, owned by the bootstrapping admin)
3. Attaches the MCP server to the agent
4. Mints the credential

```bash
# Local development
docker compose exec api python /app/scratch/bootstrap_meta_agent.py \
  --admin-email admin@dev.local \
  --ou-path /dev-org/engineering

# Production
python scratch/bootstrap_meta_agent.py \
  --api https://api.powerloom.org \
  --admin-email admin@acme.com \
  --admin-token "$JWT" \
  --ou-path /acme/platform
```

The script is idempotent. Running it twice doesn't create duplicates.

### Configuration options

| Flag | Default | Purpose |
|---|---|---|
| `--name` | `powerloom-meta` | Agent and deployment slug |
| `--display-name` | `Powerloom Meta` | Display name in the console |
| `--model` | `claude-opus-4-6` | Model for the meta-agent |
| `--system-prompt-file` | built-in | Custom system prompt override |
| `--ou-path` | required | OU where the meta-agent lives |

After bootstrap, the meta-agent appears in your Agents list and can be invoked by any user with `agent:invoke` permission on its OU.

---

## Best Practices

**State your goal, not the steps.** "Set up a code review agent for engineering" is better than "First list the OUs, then find the user, then create the agent..." The meta-agent knows the dependency order.

**Name the OU when it matters.** If your organization has multiple teams, specify where the agent should live. The meta-agent will ask if you don't, but being explicit saves a round trip.

**Check before you create.** Ask "What agents exist in engineering?" before creating a new one. The meta-agent checks for existing resources, but you'll have better context about whether something should be reused or replaced.

**Use it for provisioning, not troubleshooting.** The meta-agent is optimized for creating and wiring resources. For debugging reconciler issues, checking sync state, or diagnosing session failures, the CLI and API give you more direct access.

**Trust the error messages.** When the meta-agent hits a wall — permission denied, approval required, resource not found — it surfaces the raw API error. The error message is the diagnosis. Act on it directly.
