How It Works
Architecture
TAP is a Rust proxy (axum) backed by SQLite. Credential values are encrypted at rest with AES-256-GCM. There is no config file — everything is managed via the admin dashboard or API.
| Component | Purpose |
|---|---|
| Proxy | HTTP service: auth, policy, credential injection, forwarding, response sanitization |
| Telegram bot | Sends approve/deny requests to your Telegram for write operations |
| OAuth 1.0a signer | Sidecar for APIs that require OAuth signing (Twitter/X) |
CLI (tap) | Local management tool for self-hosted deployments |
How Agents Use TAP
The agent sends a credential name via the X-TAP-Credential header. The proxy handles everything else — auth header injection, OAuth signing, sidecar routing. The agent never knows whether the credential is a simple API key or requires OAuth.
POST /forward
X-TAP-Key: <agent-api-key>
X-TAP-Credential: slack
X-TAP-Target: https://slack.com/api/conversations.list
X-TAP-Method: GETRequest Flow
Agent request
|
v
Authentication (X-TAP-Key -> agent lookup)
|
v
Credential check (is this credential allowed for this agent?)
|
v
Rate limit check (per-agent hourly limit)
|
v
Policy evaluation
|
+-- Auto-approved (GET by default) -> skip to Forward
|
v
Human approval (Telegram or passkey)
|
v
Credential injection + forward to target API
|
v
Response sanitization (scrub credential values)
|
v
Audit log + return response to agentKey Concepts
| Concept | What it means |
|---|---|
| Credential | An API key, OAuth token, or other secret. Stored encrypted, never shown to agents |
| Agent | An AI system with a unique API key. References credentials by name |
| Role | Groups credentials for RBAC. An agent’s permissions are the union of its roles + direct assignments |
| Policy | Per-credential rules: which HTTP methods auto-approve, which need human approval |
| Team | Isolation boundary. Each team has its own credentials, agents, roles, and policies |
Response Sanitization
Before returning API responses to the agent, the proxy scans for credential leakage:
- Exact match — the literal credential value
- Base64 variant — the base64-encoded credential
- URL-encoded variant — the percent-encoded credential
Matches are replaced with [REDACTED:credential-name]. Responses larger than 10 MB pass through without scanning.
Trust Model
- Agents are untrusted — they authenticate with API keys but cannot access credential values, bypass policy, or see unsanitized responses
- The proxy is trusted — it holds encryption keys and decrypted credential values in memory during request processing
- Admins are trusted — they manage credentials and policies via the dashboard. Credential values are write-only (never returned by any API endpoint)
- Approvers are semi-trusted — they see request details (URL, method, body preview) but not credential values