AgentGate
Human-in-the-loop approval system for AI agents.
Agents request. Policies decide. Humans approve.
Keep humans in control of what AI agents can do.
Your AI agent wants to send an email, delete a file, or deploy to production.
Should it? AgentGate lets you define policies that auto-approve safe actions,
auto-deny dangerous ones, and route everything else to a human β via dashboard, Slack, Discord, or email.
β¨ Highlights
- π‘οΈ Policy engine β auto-approve, auto-deny, or route to humans based on rules
- π₯ Multi-channel approvals β Slack, Discord, email, or web dashboard
- π TypeScript SDK + MCP β works with any agent framework or Claude Desktop
- πͺ Webhooks with retry β real-time notifications with exponential backoff
- π Full audit trail β every request, decision, and action logged, each policy decision tagged with the OWASP LLM Top-10 risk it mitigates (compliance evidence)
- π³ Docker-ready β one
docker-compose up for the full stack
- π Production-hardened β SSRF protection, ReDoS defense, structured logging, graceful shutdown
- π One-click decision links β approve or deny directly from notification emails and webhooks
- βΏ Accessible UI β keyboard-navigable approval modals, focus trapping, ARIA labels
- π Skeleton loading β smooth loading states across every dashboard page
- β‘ Fast & lightweight β Hono server, SQLite or PostgreSQL
Quickstart
docker compose up
pnpm install && pnpm --filter @agentkitai/agentgate-server db:migrate && pnpm --filter @agentkitai/agentgate-server bootstrap && pnpm dev
Drop AgentGate into an MCP client (Claude Desktop / Cursor / VS Code) β point it at the gateway:
{ "mcpServers": { "agentgate": { "command": "npx", "args": ["@agentkitai/agentgate-mcp"] } } }
Dashboard
See all pending requests at a glance, color-coded by urgency so you know what needs attention first.

Approval Requests
Review, approve, or deny requests β filter by status to focus on what matters.

Audit Log
Search through every decision with filters for event type, action, actor, and date range.

Request Detail
Drill into any request to see parameters, context, timeline, and audit trail β with one-click Approve/Deny buttons.

API Keys
Manage API keys with fine-grained scopes, rate limits, and usage tracking. Create, edit, or revoke keys from the dashboard.

Webhooks
Configure webhook endpoints for real-time notifications. Add URLs, pick events, and let AgentGate handle retries automatically.

Login
Sign in with your API key β create one via the CLI or ask your admin.

Table of Contents
Quick Start
1. Install dependencies
2. Run database migrations
pnpm --filter @agentkitai/agentgate-server db:migrate
3. Bootstrap (create admin API key)
pnpm --filter @agentkitai/agentgate-server bootstrap
Save the API key - it's shown once only! Set it in your environment:
export AGENTGATE_API_KEY="agk_..."
4. Start the development environment
5. Run the demo
In a new terminal (with API key set):
export AGENTGATE_API_KEY="agk_..."
pnpm demo
6. Open the dashboard
Visit http://localhost:5173 to view and manage approval requests.
Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AI Agents β
β (use @agentkitai/agentgate-sdk or MCP to request approvals) β
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β HTTP API (authenticated)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AgentGate Server β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Policy Engineβ β Request Storeβ β Audit Logger β β
β ββββββββββββββββ€ ββββββββββββββββ€ ββββββββββββββββ€ β
β β API Keys β β Webhooks β β MCP Server β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββ
β Web Dashboard β β Slack Bot β β Discord Bot β
β(React+Tailwind)β β(approve in DM) β β(approve in ch) β
ββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββ
β β β
βββββββββββββββΌββββββββββββββ
βΌ
ββββββββββββ
β Humans β
ββββββββββββ
Packages
SDK Usage
import { AgentGateClient } from '@agentkitai/agentgate-sdk';
const client = new AgentGateClient({
baseUrl: 'http://localhost:3000',
apiKey: process.env.AGENTGATE_API_KEY,
});
const request = await client.request({
action: 'send_email',
params: {
to: 'customer@example.com',
subject: 'Order shipped!',
},
urgency: 'normal',
});
const decided = await client.waitForDecision(request.id, {
timeout: 60000,
});
if (decided.status === 'approved') {
await sendEmail(decided.params);
} else {
console.log('Action denied:', decided.decisionReason);
}
CLI
AgentGate includes a command-line interface for managing approval requests.
Installation
pnpm --filter @agentkitai/agentgate-cli build
npm install -g @agentkitai/agentgate-cli
Configuration
Configure the CLI with your server URL and API key:
agentgate config set serverUrl http://localhost:3000
agentgate config set apiKey agk_your_api_key
agentgate config show
Configuration is stored in ~/.agentgate/config.json. You can also use environment variables:
export AGENTGATE_URL=http://localhost:3000
export AGENTGATE_API_KEY=agk_...
Commands
| Command | Description |
|---|
agentgate config show | Show current configuration |
agentgate config set <key> <value> | Set a configuration value |
agentgate request <action> | Create a new approval request |
agentgate status <id> | Get status of a request |
agentgate list | List approval requests |
agentgate approve <id> | Approve a pending request |
agentgate deny <id> | Deny a pending request |
Examples
agentgate request send_email \
--params '{"to": "user@example.com", "subject": "Hello"}' \
--urgency high
agentgate list --status pending
agentgate approve req_abc123 --reason "Looks good"
agentgate deny req_abc123 --reason "Not authorized"
agentgate list --json
MCP Integration
AgentGate includes a Model Context Protocol (MCP) server for integration with Claude Desktop and other MCP-compatible clients.
Claude Desktop Configuration
Add to your claude_desktop_config.json:
{
"mcpServers": {
"agentgate": {
"command": "npx",
"args": ["@agentkitai/agentgate-mcp"],
"env": {
"AGENTGATE_URL": "http://localhost:3000",
"AGENTGATE_API_KEY": "agk_..."
}
}
}
}
| Tool | Description |
|---|
agentgate_request | Submit a new approval request |
agentgate_get | Get the status of an approval request by ID |
agentgate_list | List approval requests with optional filters |
agentgate_decide | Approve or deny a pending request |
agentgate_list_policies | List all policies ordered by priority |
agentgate_create_policy | Create a new policy with rules |
agentgate_update_policy | Replace an existing policy |
agentgate_delete_policy | Delete a policy by ID |
agentgate_list_audit_logs | List audit log entries with filters and pagination |
agentgate_get_audit_actors | Get unique actor values from audit logs |
Authentication
AgentGate uses API keys for authentication. All API requests (except /health) require a valid API key.
API Key Scopes
| Scope | Description |
|---|
admin | Full access to all operations |
request:create | Create new approval requests |
request:read | Read approval requests |
request:decide | Approve or deny requests |
webhook:manage | Create/update/delete webhooks |
Using API Keys
HTTP Header:
curl -H "Authorization: Bearer agk_..." http://localhost:3000/api/requests
SDK:
const client = new AgentGateClient({
baseUrl: 'http://localhost:3000',
apiKey: process.env.AGENTGATE_API_KEY,
});
Creating Additional API Keys
POST /api/api-keys
{
"name": "My Agent",
"scopes": ["request:create", "request:read"]
}
API Endpoints
| Method | Endpoint | Description | Required Scope |
|---|
POST | /api/requests | Create approval request | request:create |
GET | /api/requests | List requests (with filters) | request:read |
GET | /api/requests/:id | Get request by ID | request:read |
POST | /api/requests/:id/decide | Submit approval/denial | request:decide |
GET | /api/requests/:id/audit | Get audit trail | request:read |
GET | /api/policies | List policies | admin |
POST | /api/policies | Create policy | admin |
PUT | /api/policies/:id | Update policy | admin |
DELETE | /api/policies/:id | Delete policy | admin |
POST | /api/api-keys | Create API key | admin |
GET | /api/api-keys | List API keys | admin |
PATCH | /api/api-keys/:id | Update API key | admin |
DELETE | /api/api-keys/:id | Revoke API key | admin |
GET | /api/webhooks | List webhooks | webhook:manage |
POST | /api/webhooks | Create webhook | webhook:manage |
DELETE | /api/webhooks/:id | Delete webhook | webhook:manage |
GET | /health | Health check | (none) |
Rate Limiting
AgentGate supports per-API-key rate limiting to prevent abuse and ensure fair usage.
How It Works
- Rate limits use a sliding window algorithm (requests per minute)
- Limits are configured per API key
- When exceeded, requests return
429 Too Many Requests
- Rate limit headers are included in all authenticated responses
| Header | Description |
|---|
X-RateLimit-Limit | Maximum requests per minute |
X-RateLimit-Remaining | Remaining requests in current window |
X-RateLimit-Reset | Seconds until window resets |
Configuring Rate Limits
Set rate limits when creating or updating API keys:
POST /api/api-keys
{
"name": "My Agent",
"scopes": ["request:create", "request:read"],
"rateLimit": 60
}
{
"name": "Internal Service",
"scopes": ["admin"],
"rateLimit": null
}
Dashboard
Rate limits can also be managed from the web dashboard under Settings β API Keys.
Webhooks
AgentGate can notify external systems when request events occur.
Setting Up Webhooks
POST /api/webhooks
{
"url": "https://your-server.com/webhook",
"events": ["request.created", "request.decided"],
"secret": "optional-signing-secret"
}
Webhook Events
| Event | Description |
|---|
request.created | A new approval request was created |
request.decided | A request was approved or denied |
request.expired | A request expired without decision |
Webhook Payload
{
"event": "request.decided",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "abc123",
"action": "send_email",
"status": "approved",
"decidedBy": "admin@example.com"
}
}
Webhook Signatures
If you provide a secret, requests are signed with HMAC-SHA256:
X-AgentGate-Signature: sha256=...
Verify by computing HMAC-SHA256(secret, body) and comparing.
Webhook Retry
Failed webhook deliveries are retried automatically with exponential backoff. The server scans for pending deliveries and retries them with increasing delays (2^attempts * 1000ms) until successful or the maximum retry count is reached.
Configuration
Environment Variables
| Variable | Default | Description |
|---|
PORT | 3000 | Server port |
DATABASE_URL | ./data/agentgate.db | SQLite database path |
AGENTGATE_API_KEY | - | API key for SDK/CLI |
SLACK_BOT_TOKEN | - | Slack bot token (for Slack integration) |
SLACK_SIGNING_SECRET | - | Slack signing secret |
DISCORD_BOT_TOKEN | - | Discord bot token (for Discord integration) |
DISCORD_DEFAULT_CHANNEL | - | Default Discord channel for notifications |
File-Based Secrets (_FILE suffix)
For Docker secrets or Kubernetes secret mounts, AgentGate supports a _FILE suffix convention. Instead of setting a secret directly in an environment variable, point to a file containing the value:
| Variable | Reads secret from file |
|---|
ADMIN_API_KEY_FILE | Sets ADMIN_API_KEY |
JWT_SECRET_FILE | Sets JWT_SECRET |
DATABASE_URL_FILE | Sets DATABASE_URL |
REDIS_URL_FILE | Sets REDIS_URL |
SLACK_BOT_TOKEN_FILE | Sets SLACK_BOT_TOKEN |
SLACK_SIGNING_SECRET_FILE | Sets SLACK_SIGNING_SECRET |
DISCORD_BOT_TOKEN_FILE | Sets DISCORD_BOT_TOKEN |
SMTP_PASS_FILE | Sets SMTP_PASS |
Behavior:
- File contents are trimmed of leading/trailing whitespace
- If both the env var and the
_FILE variant are set, the explicit env var takes precedence
- Missing or unreadable files produce a warning but do not crash the server
Example with Docker Compose:
services:
agentgate:
environment:
ADMIN_API_KEY_FILE: /run/secrets/admin_api_key
JWT_SECRET_FILE: /run/secrets/jwt_secret
secrets:
- admin_api_key
- jwt_secret
secrets:
admin_api_key:
file: ./secrets/admin_api_key.txt
jwt_secret:
file: ./secrets/jwt_secret.txt
Policy Configuration
Policies are stored in the database and can be managed via API:
{
name: "auto-approve-emails",
priority: 10,
enabled: true,
rules: [
{
match: { action: "send_email" },
decision: "auto_approve"
}
]
}
Docker Deployment
AgentGate provides Docker images for easy self-hosted deployments.
Quick Start
- Copy the example environment file:
- Generate secure credentials:
echo "ADMIN_API_KEY=$(openssl rand -hex 32)" >> .env
echo "JWT_SECRET=$(openssl rand -hex 32)" >> .env
- Start all services:
- Access the services:
Host ports are configurable via SERVER_PORT (default 3002) and DASHBOARD_PORT (default 3003); both map to the container's internal port 3000/80.
Services
| Service | Description | Host Port |
|---|
server | AgentGate API server | 3002 |
dashboard | Web dashboard (nginx) | 3003 |
postgres | PostgreSQL database | internal only* |
redis | Redis (rate limiting, queues) | internal only* |
* PostgreSQL and Redis are on an internal Docker network (agentgate-internal) and are not exposed to the host by default. During development, docker-compose.override.yml is auto-loaded and exposes them on ports 5432/6379. For production, run docker-compose -f docker-compose.yml up -d to skip the override.
With Slack or Discord Bots
To include the bot services, use the bots profile:
docker-compose --profile bots up -d
Configuration
All configuration is done via environment variables. See .env.example for all options.
Required variables:
ADMIN_API_KEY β Admin API key (min 16 characters)
Recommended for production:
JWT_SECRET β JWT signing secret (min 32 characters)
CORS_ALLOWED_ORIGINS β Restrict to your domain(s)
POSTGRES_PASSWORD β Use a strong password
Building Images
Build all images locally:
Build a specific service:
docker-compose build server
docker-compose build dashboard
Database Migrations
Migrations run automatically when the server starts. For manual control:
docker-compose exec server node -e "
import('./dist/db/migrate.js').then(m => m.runMigrations())
"
Viewing Logs
docker-compose logs -f
docker-compose logs -f server
docker-compose logs --tail=100 server
Stopping Services
docker-compose down
docker-compose down -v
Production Considerations
- Use a reverse proxy (nginx, Caddy, Traefik) for TLS termination
- Set strong passwords for PostgreSQL
- Restrict CORS origins to your domain
- Use Docker secrets for sensitive values in production
- Set up backups for PostgreSQL data volume
- Monitor health endpoints for uptime checks
Development
pnpm install
pnpm --filter @agentkitai/agentgate-server db:migrate
pnpm --filter @agentkitai/agentgate-server bootstrap
pnpm dev
Testing
AgentGate uses Vitest for testing across all packages.
pnpm test
pnpm test:coverage
pnpm --filter @agentkitai/agentgate-server test:watch
pnpm --filter @agentkitai/agentgate-server test -- src/__tests__/integration.test.ts
Coverage reports are generated per-package and include line, branch, and function coverage.
Code Quality
pnpm build
pnpm typecheck
pnpm lint
pnpm lint:fix
pnpm format
pnpm format:check
Project Structure
agentgate/
βββ packages/
β βββ core/ # Shared types, schemas, policy engine
β βββ server/ # Hono API server
β βββ sdk/ # TypeScript SDK
β βββ cli/ # Command-line interface
β βββ mcp/ # MCP server for Claude Desktop
β βββ slack/ # Slack bot
β βββ discord/ # Discord bot
β βββ dashboard/ # React dashboard
βββ apps/
β βββ demo/ # Demo application
βββ docker-compose.yml # Docker deployment
βββ package.json # Monorepo root
Contributing
Contributions are welcome! To get started:
- Fork the repository
- Clone and install dependencies (
pnpm install)
- Follow the Development section above to set up your local environment
- Create a feature branch and make your changes
- Run
pnpm build && pnpm test to verify everything works
- Open a pull request
Please make sure all tests pass and code is formatted (pnpm format:check && pnpm lint) before submitting.
π§° AgentKit Ecosystem
| Project | Description | |
|---|
| AgentLens | Observability & audit trail for AI agents | |
| Lore | Cross-agent memory and lesson sharing | |
| AgentGate | Human-in-the-loop approval gateway | β¬
οΈ you are here |
| FormBridge | Agent-human mixed-mode forms | |
| AgentEval | Testing & evaluation framework | |
| agentkit-cli | Unified CLI orchestrator | |
License
MIT