Quickstart

Quickstart

Get TAP running and proxying your first request.

The fastest and most secure way to run TAP. Your encryption keys are generated and stored inside hardware enclaves — they never touch your machine, your clipboard, or a .env file. No infrastructure to set up.

Dashboard: You can do all of the below steps visually at auth.toolsec.org instead of using curl. The API examples below are for automation and scripting.

1. Sign Up and Create a Team

curl -X POST https://api.toolsec.org/signup \
  -H "Content-Type: application/json" \
  -d '{"team_name": "my-team", "email": "you@example.com", "password": "your-password"}'

You will receive a verification email. Verify with the 6-digit code:

curl -X POST https://api.toolsec.org/verify-email \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "code": "123456"}'

2. Log In

curl -X POST https://api.toolsec.org/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "your-password"}'

Save the session_token from the response — you will use it for all admin API calls:

export ADMIN_TOKEN="<session_token from response>"

3. Add a Credential

curl -X POST https://api.toolsec.org/admin/credentials \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "openai",
    "description": "OpenAI API",
    "connector": "direct",
    "value": "sk-your-openai-key"
  }'

The credential value is encrypted at rest and never returned by any API endpoint.

4. Set a Policy

curl -X PUT https://api.toolsec.org/admin/policies/openai \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "auto_approve_methods": ["GET", "POST"],
    "require_approval_methods": ["DELETE"]
  }'

5. Create an Agent

curl -X POST https://api.toolsec.org/admin/agents \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "my-agent",
    "description": "My first agent",
    "credentials": ["openai"]
  }'

Save the api_key from the response — it is shown only once:

export AGENT_KEY="<api_key from response>"

6. Send a Request Through the Proxy

curl -X POST https://api.toolsec.org/forward \
  -H "X-TAP-Key: $AGENT_KEY" \
  -H "X-TAP-Credential: openai" \
  -H "X-TAP-Target: https://api.openai.com/v1/models" \
  -H "X-TAP-Method: GET"

The proxy authenticates your agent, checks the policy (GET is auto-approved), injects the real API key into the Authorization: Bearer header, forwards the request to OpenAI, scrubs any credential values from the response, and returns it.

Your agent never saw the actual API key.


Self-Hosted

Run the proxy on your own infrastructure. Same proxy, same API — you manage the keys.

Prerequisites

  • Docker and Docker Compose
  • A Telegram bot token (create one via @BotFather)
  • The chat ID where approval messages should go (use @userinfobot or a group chat ID)

1. Clone and Configure

git clone https://github.com/anthropics/agentsec.git
cd agentsec
cp local.env.example .env

Generate an encryption key and edit .env:

# Generate a 32-byte encryption key
openssl rand -hex 32

Fill in .env:

AGENTSEC_ENCRYPTION_KEY=<paste-64-hex-chars>
TELEGRAM_BOT_TOKEN=<your-bot-token>
TELEGRAM_CHAT_ID=<your-chat-id>

2. Start the Proxy

docker-compose -f docker-compose.yaml -f docker-compose.local.yaml up --build

The proxy listens on http://localhost:3100. No TLS in local mode.

3. Sign Up as Admin

Even when self-hosted, admin accounts use the same signup/login flow:

curl -X POST http://localhost:3100/signup \
  -H "Content-Type: application/json" \
  -d '{"team_name": "my-team", "email": "you@example.com", "password": "your-password"}'

In local mode, if email sending fails, the verification code is logged to the console. Check your Docker logs and verify:

curl -X POST http://localhost:3100/verify-email \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "code": "123456"}'

Then log in:

curl -X POST http://localhost:3100/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "your-password"}'
 
export ADMIN_TOKEN="<session_token from response>"

4. Add a Credential and Create an Agent

# Create a credential
curl -X POST http://localhost:3100/admin/credentials \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "openai",
    "description": "OpenAI API",
    "connector": "direct",
    "value": "sk-your-openai-key"
  }'
 
# Set auto-approve policy for GET requests
curl -X PUT http://localhost:3100/admin/policies/openai \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"auto_approve_methods": ["GET"]}'
 
# Create an agent
curl -X POST http://localhost:3100/admin/agents \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "my-agent",
    "description": "Test agent",
    "credentials": ["openai"]
  }'
 
export AGENT_KEY="<api_key from response>"

5. Test It

# Auto-approved GET request
curl -X POST http://localhost:3100/forward \
  -H "X-TAP-Key: $AGENT_KEY" \
  -H "X-TAP-Credential: openai" \
  -H "X-TAP-Target: https://api.openai.com/v1/models" \
  -H "X-TAP-Method: GET"

6. Try a Request That Requires Approval

If your policy only auto-approves GET, a POST will trigger a Telegram approval:

curl -X POST http://localhost:3100/forward \
  -H "X-TAP-Key: $AGENT_KEY" \
  -H "X-TAP-Credential: openai" \
  -H "X-TAP-Target: https://api.openai.com/v1/chat/completions" \
  -H "X-TAP-Method: POST" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}'

The curl command blocks until the approver responds via Telegram (tap Approve/Deny) or passkey (Face ID, fingerprint, YubiKey). Default timeout: 5 minutes.


What Just Happened?

The proxy authenticated your agent via X-TAP-Key, looked up the openai credential by name, checked the policy, injected the real API key into the Authorization: Bearer header, forwarded the request, and scrubbed any credential values from the response.

Your agent’s code barely changes. Any tool or skill that makes API calls works the same way — use a credential name where you would normally put a raw secret. The agent does not need to know whether a credential is an API key, an OAuth token, or something custom. The proxy abstracts that away.

Next Steps

  • How It Works — understand the full request flow and architecture
  • Configuration — manage credentials, agents, roles, and policies via the dashboard or API
  • Policies & Approval — configure auto-approve rules and approval routing
  • Deployment — run in production with TLS