# Pi Integration

Connect Pi to Capsule Security for complete visibility into AI coding agent activity, including tool execution, sessions, prompts and agent replies - with inline blocking on policy-violating tool calls and prompts.

## Overview

This integration uses [Pi's extension system](https://pi.dev/docs/latest/extensions) to capture and govern AI coding agent activity. The Capsule extension runs in-process inside Pi, forwards every hook event to your Capsule tenant over HTTPS, and applies policy verdicts to tool calls before they execute and to prompts before they reach the model.

The following hooks are configured:

| Hook Event | Type | Description |
|  --- | --- | --- |
| **tool_call** | Blocking | Tool execution requests - can block the call and surface the policy reason in the terminal |
| **input** | Blocking | The prompt the developer submitted - can drop it before it reaches the model |
| **tool_result** | Observation | Tool output after execution |
| **tool_execution_start** | Observation | Tool execution began |
| **tool_execution_end** | Observation | Tool execution finished |
| **session_start** | Observation | Session initialization |
| **session_shutdown** | Observation | Session termination and cleanup |
| **agent_start** | Observation | Low-level agent run started |
| **agent_end** | Observation | Low-level agent run finished |
| **before_agent_start** | Observation | The prompt after Pi expands a skill or prompt-template command |
| **turn_start** | Observation | An LLM response and tool-call cycle began |
| **turn_end** | Observation | An LLM response and tool-call cycle finished, including the agent reply |
| **user_bash** | Observation | Commands run with `!` or `!!` outside the tool loop |
| **context** | Observation | Full model context, only when `allowConversationAccess` is enabled |


A blocked prompt is not sent to the model, and the policy reason is shown as a Pi notification (on stderr in print mode). `input` also covers steer and follow-up messages sent while the agent is running, so every prompt waits for the policy verdict before it is sent.

Pi expands `/skill:name` and prompt-template commands after `input`, so the policy check sees the command as typed, including its arguments. The expanded prompt is recorded through `before_agent_start`, but Pi cannot cancel a prompt at that point, so content that comes from the skill or template file is audited, not blocked.

`user_bash` runs outside Pi's tool loop and does not accept a verdict, so those commands are audited but not enforced.

## Prerequisites

Before you begin, ensure you have:

- **Pi** installed (Node.js 18 or later)
- A **Capsule Security** account with admin access
- Network access from your developer machines to your Capsule agentsecurity endpoint (e.g. `https://agents.capsule.security`)


## Step 1: Generate an Extension Token

1. Log in to the **Capsule Security** portal
2. Navigate to **Integrations** and locate **Pi**
3. Click **Install** - Capsule generates a JWT scoped to your tenant and Pi environment. The token contains the tenant and environment claims required by the agentsecurity endpoint; treat it as a secret.
4. Copy the generated token. You will reference it from your Capsule extension configuration in the next step.


## Step 2: Register the Extension

Pi installs extensions from npm through the `packages` array in `settings.json`. Add the Capsule package to `~/.pi/agent/settings.json` for every project, or to `.pi/settings.json` for a single project:

```json
{
  "packages": ["npm:@capsulesecurity/pi-capsule"]
}
```

Pi resolves and installs the package on next start. To pin a version, use `"npm:@capsulesecurity/pi-capsule@1.2.0"`.

## Step 3: Configure the Extension

Pi has no per-extension configuration block in `settings.json`, so the Capsule extension reads its settings from `~/.pi/capsule.json`:

```json
{
  "endpoint": "https://agents.capsule.security",
  "token": "<token-from-step-1>",
  "blockOnRisk": true,
  "failOpen": true,
  "timeoutMs": 5000,
  "allowConversationAccess": false
}
```

### Configuration Options

Every option can also be supplied as an environment variable.

`endpoint` and `token` come from the environment when both are set there, otherwise from `~/.pi/capsule.json`, and
the remaining settings come from that same source. Environment variables still override the other options. A
project-level `.pi/capsule.json` is never read, so cloning an untrusted repository cannot redirect your prompts and
tool calls to someone else's server or turn enforcement off.

| Option | Env var | Type | Default | Description |
|  --- | --- | --- | --- | --- |
| `endpoint` | `CAPSULE_ENDPOINT` | `string` | *(required)* | Capsule agentsecurity endpoint, e.g. `https://agents.capsule.security` |
| `token` | `CAPSULE_TOKEN` | `string` | *(required)* | JWT generated in Step 1, scoped to your tenant and environment |
| `blockOnRisk` | `CAPSULE_BLOCK_ON_RISK` | `boolean` | `true` | Apply server `block` decisions inline. Set to `false` to run in observe-only mode |
| `failOpen` | `CAPSULE_FAIL_OPEN` | `boolean` | `true` | When Capsule is unreachable or returns an error, allow the tool or prompt. Set to `false` to fail closed |
| `timeoutMs` | `CAPSULE_TIMEOUT_MS` | `number` | `5000` | Per-request timeout in milliseconds |
| `allowConversationAccess` | `CAPSULE_ALLOW_CONVERSATION_ACCESS` | `boolean` | `false` | When `true`, forward the model context transcript to Capsule. Required for full conversation observability and policies that rely on conversation context |
| `user` | `CAPSULE_USER` | `string` | `process.env.USER` | User identifier sent on every event |


Without `endpoint` and `token` the extension logs a warning and stays inactive. It never breaks the agent loop.

### Token Storage

Never commit the JWT to version control. Recommended approaches:

- Keep the token in `~/.pi/capsule.json` outside any repository
- Set `CAPSULE_TOKEN` from your secret manager (1Password, AWS Secrets Manager, HashiCorp Vault) at shell startup
- For MDM-managed deployments, deliver it through the same channel that distributes the Pi configuration


## Step 4: Restart Pi

For the extension to take effect, restart any running Pi sessions:

1. Exit Pi
2. Restart Pi so it installs the package and loads the extension


## Step 5: Verify the Installation

1. Start a new Pi session and execute a simple task to generate activity:

```
Create a new file called test.txt with the content "Hello World"
```
2. Log in to the **Capsule Security** portal
3. Navigate to **Inventory > Agents** and confirm your Pi agent appears. Pi has no persistent agent identifier, so an agent is identified by the working directory and the user running it.
4. Click on the agent and review the audit logs to verify events are captured:
  - Session start event
  - Tool execution (write tool)
  - The prompt you submitted and the agent reply
  - Session activity
5. To view the full conversation, navigate to **Observability** and filter by **Activity Type - Session** (requires `allowConversationAccess: true`)


### Troubleshooting

If events are not appearing:

1. **Verify the endpoint is reachable** from the host running Pi:

```bash
curl -sS -o /dev/null -w "%{http_code}\n" https://agents.capsule.security/health
```
2. **Verify the configuration is found** - the extension logs a warning on startup and stays inactive when `endpoint` or `token` is missing. Check that `~/.pi/capsule.json` is valid JSON.
3. **Check for timeouts** - if your network has high latency to the Capsule endpoint, increase `timeoutMs` or confirm `failOpen` is set appropriately.
4. **Confirm the extension is loaded** - Pi lists active extensions on startup. Run `pi -e` against the installed package path to test loading in isolation.
5. **Check project trust** - a project-local `.pi/settings.json` is only honoured after you trust the project directory. Install the package in `~/.pi/agent/settings.json` to avoid the trust gate.
6. **Contact Capsule Security support** if issues persist.


## Security Considerations

The Capsule extension runs in-process inside Pi with full system permissions and observes every tool call, prompt and agent reply. Before deploying:

1. **Protect the JWT** - anyone with the token can post events on behalf of your tenant. Rotate it through the portal if it is exposed.
2. **Choose `failOpen` deliberately** - `failOpen: true` (the default) prioritizes developer productivity; `failOpen: false` prioritizes policy enforcement and will block tool execution and prompts when Capsule is unreachable.
3. **Decide on conversation access explicitly** - `allowConversationAccess: true` forwards the model context to Capsule. Enable this only after reviewing the data residency and retention implications with your security and privacy teams.
4. **Pin an extension version** in production, using `"npm:@capsulesecurity/pi-capsule@&lt;version&gt;"`, and review changelogs before upgrading.
5. **Use TLS-only endpoints**. The extension sends a Bearer token on every request - never configure an `http://` endpoint.
6. **Understand the coverage boundary** - the extension loads in Pi's interactive, batch and RPC modes. Commands run with `!` or `!!` are audited but cannot be blocked.


## Support

For help with this integration:

- **Email**: support@capsule.security
- **Include**: Your organization ID, integration status, extension version, and any error messages


## References

- [Pi Documentation](https://pi.dev/docs/latest)
- [Pi Extension API](https://pi.dev/docs/latest/extensions)
- [Capsule Pi Extension on npm](https://www.npmjs.com/package/@capsulesecurity/pi-capsule)