{
  "markdown": "<p align=\"center\">\n  <h1 align=\"center\">AgentGate</h1>\n  <p align=\"center\">\n    <strong>Human-in-the-loop approval system for AI agents.</strong><br>\n    Agents request. Policies decide. Humans approve.<br>\n    <em>Keep humans in control of what AI agents can do.</em>\n  </p>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/search?q=%40agentgate\"><img src=\"https://img.shields.io/npm/v/@agentkitai/agentgate-sdk?label=sdk&color=blue\" alt=\"npm version\"></a>\n  <a href=\"./LICENSE\"><img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"MIT License\"></a>\n  <a href=\"https://github.com/agentkitai/agentgate/actions\"><img src=\"https://img.shields.io/github/actions/workflow/status/agentkitai/agentgate/ci.yml?branch=main\" alt=\"CI\"></a>\n  <a href=\"#\"><img src=\"https://img.shields.io/badge/TypeScript-5.x-blue?logo=typescript&logoColor=white\" alt=\"TypeScript\"></a>\n</p>\n\n---\n\n<p align=\"center\">\n  <img src=\"docs/public/demo.gif\" alt=\"AgentGate Demo\" width=\"700\">\n</p>\n\nYour AI agent wants to send an email, delete a file, or deploy to production.\n**Should it?** AgentGate lets you define policies that auto-approve safe actions,\nauto-deny dangerous ones, and route everything else to a human — via dashboard, Slack, Discord, or email.\n\n### ✨ Highlights\n\n- 🛡️ **Policy engine** — auto-approve, auto-deny, or route to humans based on rules\n- 👥 **Multi-channel approvals** — Slack, Discord, email, or web dashboard\n- 🔌 **TypeScript SDK + MCP** — works with any agent framework or Claude Desktop\n- 🪝 **Webhooks with retry** — real-time notifications with exponential backoff\n- 📝 **Full audit trail** — every request, decision, and action logged, each policy decision tagged with the **OWASP LLM Top-10** risk it mitigates (compliance evidence)\n- 🐳 **Docker-ready** — one `docker-compose up` for the full stack\n- 🔐 **Production-hardened** — SSRF protection, ReDoS defense, structured logging, graceful shutdown\n- 🔗 **One-click decision links** — approve or deny directly from notification emails and webhooks\n- ♿ **Accessible UI** — keyboard-navigable approval modals, focus trapping, ARIA labels\n- 💀 **Skeleton loading** — smooth loading states across every dashboard page\n- ⚡ **Fast & lightweight** — Hono server, SQLite or PostgreSQL\n\n## Quickstart\n\n```bash\n# Self-host the full stack (server + dashboard + Postgres):\ndocker compose up\n\n# …or from source:\npnpm install && pnpm --filter @agentkitai/agentgate-server db:migrate && pnpm --filter @agentkitai/agentgate-server bootstrap && pnpm dev\n```\n\nDrop AgentGate into an MCP client (Claude Desktop / Cursor / VS Code) — point it at the gateway:\n\n```jsonc\n{ \"mcpServers\": { \"agentgate\": { \"command\": \"npx\", \"args\": [\"@agentkitai/agentgate-mcp\"] } } }\n```\n\n#### Dashboard\nSee all pending requests at a glance, color-coded by urgency so you know what needs attention first.\n\n![Dashboard](docs/screenshots/dashboard.png)\n\n#### Approval Requests\nReview, approve, or deny requests — filter by status to focus on what matters.\n\n![Requests](docs/screenshots/requests.png)\n\n#### Audit Log\nSearch through every decision with filters for event type, action, actor, and date range.\n\n![Audit Log](docs/screenshots/audit-log.png)\n\n#### Request Detail\nDrill into any request to see parameters, context, timeline, and audit trail — with one-click Approve/Deny buttons.\n\n![Request Detail](docs/screenshots/request-detail.png)\n\n#### API Keys\nManage API keys with fine-grained scopes, rate limits, and usage tracking. Create, edit, or revoke keys from the dashboard.\n\n![API Keys](docs/screenshots/api-keys.png)\n\n#### Webhooks\nConfigure webhook endpoints for real-time notifications. Add URLs, pick events, and let AgentGate handle retries automatically.\n\n![Webhooks](docs/screenshots/webhooks.png)\n\n#### Login\nSign in with your API key — create one via the CLI or ask your admin.\n\n![Login](docs/screenshots/login.png)\n\n---\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Architecture](#architecture)\n- [Packages](#packages)\n- [SDK Usage](#sdk-usage)\n- [CLI](#cli)\n- [MCP Integration](#mcp-integration)\n- [Authentication](#authentication)\n- [API Endpoints](#api-endpoints)\n- [Rate Limiting](#rate-limiting)\n- [Webhooks](#webhooks)\n- [Configuration](#configuration)\n- [Docker Deployment](#docker-deployment)\n- [Development](#development)\n- [Troubleshooting](docs/troubleshooting.md)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Quick Start\n\n### 1. Install dependencies\n\n```bash\npnpm install\n```\n\n### 2. Run database migrations\n\n```bash\npnpm --filter @agentkitai/agentgate-server db:migrate\n```\n\n### 3. Bootstrap (create admin API key)\n\n```bash\npnpm --filter @agentkitai/agentgate-server bootstrap\n```\n\n**Save the API key** - it's shown once only! Set it in your environment:\n\n```bash\nexport AGENTGATE_API_KEY=\"agk_...\"\n```\n\n### 4. Start the development environment\n\n```bash\n# Start server (port 3000) and dashboard (port 5173)\npnpm dev\n```\n\n### 5. Run the demo\n\nIn a new terminal (with API key set):\n\n```bash\nexport AGENTGATE_API_KEY=\"agk_...\"\npnpm demo\n```\n\n### 6. Open the dashboard\n\nVisit **http://localhost:5173** to view and manage approval requests.\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                         AI Agents                                │\n│  (use @agentkitai/agentgate-sdk or MCP to request approvals)               │\n└───────────────────────────┬─────────────────────────────────────┘\n                            │ HTTP API (authenticated)\n                            ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                    AgentGate Server                              │\n│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │\n│  │ Policy Engine│  │ Request Store│  │ Audit Logger │          │\n│  ├──────────────┤  ├──────────────┤  ├──────────────┤          │\n│  │  API Keys    │  │  Webhooks    │  │  MCP Server  │          │\n│  └──────────────┘  └──────────────┘  └──────────────┘          │\n└───────────────────────────┬─────────────────────────────────────┘\n                            │\n              ┌─────────────┼─────────────┐\n              ▼             ▼             ▼\n┌────────────────┐ ┌────────────────┐ ┌────────────────┐\n│  Web Dashboard │ │   Slack Bot    │ │  Discord Bot   │\n│(React+Tailwind)│ │(approve in DM) │ │(approve in ch) │\n└────────────────┘ └────────────────┘ └────────────────┘\n              │             │             │\n              └─────────────┼─────────────┘\n                            ▼\n                      ┌──────────┐\n                      │  Humans  │\n                      └──────────┘\n```\n\n## Packages\n\n| Package | Description | Docs |\n|---------|-------------|------|\n| [`@agentkitai/agentgate-core`](./packages/core) | Types, schemas, policy engine | - |\n| [`@agentkitai/agentgate-server`](./packages/server) | Hono API server | - |\n| [`@agentkitai/agentgate-sdk`](./packages/sdk) | TypeScript SDK for agents | [README](./packages/sdk/README.md) |\n| [`@agentkitai/agentgate-cli`](./packages/cli) | Command-line interface | - |\n| [`@agentkitai/agentgate-mcp`](./packages/mcp) | MCP server for Claude Desktop | - |\n| [`@agentkitai/agentgate-slack`](./packages/slack) | Slack bot integration | [README](./packages/slack/README.md) |\n| [`@agentkitai/agentgate-discord`](./packages/discord) | Discord bot integration | [README](./packages/discord/README.md) |\n| [`@agentkitai/agentgate-dashboard`](./packages/dashboard) | React web dashboard | - |\n\n## SDK Usage\n\n```typescript\nimport { AgentGateClient } from '@agentkitai/agentgate-sdk';\n\n// Create client with API key\nconst client = new AgentGateClient({\n  baseUrl: 'http://localhost:3000',\n  apiKey: process.env.AGENTGATE_API_KEY,\n});\n\n// Request approval\nconst request = await client.request({\n  action: 'send_email',\n  params: {\n    to: 'customer@example.com',\n    subject: 'Order shipped!',\n  },\n  urgency: 'normal',\n});\n\n// Wait for human decision\nconst decided = await client.waitForDecision(request.id, {\n  timeout: 60000, // 1 minute\n});\n\nif (decided.status === 'approved') {\n  // Execute the action\n  await sendEmail(decided.params);\n} else {\n  console.log('Action denied:', decided.decisionReason);\n}\n```\n\n## CLI\n\nAgentGate includes a command-line interface for managing approval requests.\n\n### Installation\n\n```bash\n# From the monorepo\npnpm --filter @agentkitai/agentgate-cli build\n\n# Or install globally (when published)\nnpm install -g @agentkitai/agentgate-cli\n```\n\n### Configuration\n\nConfigure the CLI with your server URL and API key:\n\n```bash\n# Set server URL\nagentgate config set serverUrl http://localhost:3000\n\n# Set API key\nagentgate config set apiKey agk_your_api_key\n\n# View current config\nagentgate config show\n```\n\nConfiguration is stored in `~/.agentgate/config.json`. You can also use environment variables:\n\n```bash\nexport AGENTGATE_URL=http://localhost:3000\nexport AGENTGATE_API_KEY=agk_...\n```\n\n### Commands\n\n| Command | Description |\n|---------|-------------|\n| `agentgate config show` | Show current configuration |\n| `agentgate config set <key> <value>` | Set a configuration value |\n| `agentgate request <action>` | Create a new approval request |\n| `agentgate status <id>` | Get status of a request |\n| `agentgate list` | List approval requests |\n| `agentgate approve <id>` | Approve a pending request |\n| `agentgate deny <id>` | Deny a pending request |\n\n### Examples\n\n```bash\n# Create a request\nagentgate request send_email \\\n  --params '{\"to\": \"user@example.com\", \"subject\": \"Hello\"}' \\\n  --urgency high\n\n# List pending requests\nagentgate list --status pending\n\n# Approve a request\nagentgate approve req_abc123 --reason \"Looks good\"\n\n# Deny a request\nagentgate deny req_abc123 --reason \"Not authorized\"\n\n# Output as JSON\nagentgate list --json\n```\n\n## MCP Integration\n\nAgentGate includes a Model Context Protocol (MCP) server for integration with Claude Desktop and other MCP-compatible clients.\n\n### Claude Desktop Configuration\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"agentgate\": {\n      \"command\": \"npx\",\n      \"args\": [\"@agentkitai/agentgate-mcp\"],\n      \"env\": {\n        \"AGENTGATE_URL\": \"http://localhost:3000\",\n        \"AGENTGATE_API_KEY\": \"agk_...\"\n      }\n    }\n  }\n}\n```\n\n### Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `agentgate_request` | Submit a new approval request |\n| `agentgate_get` | Get the status of an approval request by ID |\n| `agentgate_list` | List approval requests with optional filters |\n| `agentgate_decide` | Approve or deny a pending request |\n| `agentgate_list_policies` | List all policies ordered by priority |\n| `agentgate_create_policy` | Create a new policy with rules |\n| `agentgate_update_policy` | Replace an existing policy |\n| `agentgate_delete_policy` | Delete a policy by ID |\n| `agentgate_list_audit_logs` | List audit log entries with filters and pagination |\n| `agentgate_get_audit_actors` | Get unique actor values from audit logs |\n\n## Authentication\n\nAgentGate uses API keys for authentication. All API requests (except `/health`) require a valid API key.\n\n### API Key Scopes\n\n| Scope | Description |\n|-------|-------------|\n| `admin` | Full access to all operations |\n| `request:create` | Create new approval requests |\n| `request:read` | Read approval requests |\n| `request:decide` | Approve or deny requests |\n| `webhook:manage` | Create/update/delete webhooks |\n\n### Using API Keys\n\n**HTTP Header:**\n```bash\ncurl -H \"Authorization: Bearer agk_...\" http://localhost:3000/api/requests\n```\n\n**SDK:**\n```typescript\nconst client = new AgentGateClient({\n  baseUrl: 'http://localhost:3000',\n  apiKey: process.env.AGENTGATE_API_KEY,\n});\n```\n\n### Creating Additional API Keys\n\n```typescript\n// Via API (requires admin scope)\nPOST /api/api-keys\n{\n  \"name\": \"My Agent\",\n  \"scopes\": [\"request:create\", \"request:read\"]\n}\n```\n\n## API Endpoints\n\n| Method | Endpoint | Description | Required Scope |\n|--------|----------|-------------|----------------|\n| `POST` | `/api/requests` | Create approval request | `request:create` |\n| `GET` | `/api/requests` | List requests (with filters) | `request:read` |\n| `GET` | `/api/requests/:id` | Get request by ID | `request:read` |\n| `POST` | `/api/requests/:id/decide` | Submit approval/denial | `request:decide` |\n| `GET` | `/api/requests/:id/audit` | Get audit trail | `request:read` |\n| `GET` | `/api/policies` | List policies | `admin` |\n| `POST` | `/api/policies` | Create policy | `admin` |\n| `PUT` | `/api/policies/:id` | Update policy | `admin` |\n| `DELETE` | `/api/policies/:id` | Delete policy | `admin` |\n| `POST` | `/api/api-keys` | Create API key | `admin` |\n| `GET` | `/api/api-keys` | List API keys | `admin` |\n| `PATCH` | `/api/api-keys/:id` | Update API key | `admin` |\n| `DELETE` | `/api/api-keys/:id` | Revoke API key | `admin` |\n| `GET` | `/api/webhooks` | List webhooks | `webhook:manage` |\n| `POST` | `/api/webhooks` | Create webhook | `webhook:manage` |\n| `DELETE` | `/api/webhooks/:id` | Delete webhook | `webhook:manage` |\n| `GET` | `/health` | Health check | (none) |\n\n## Rate Limiting\n\nAgentGate supports per-API-key rate limiting to prevent abuse and ensure fair usage.\n\n### How It Works\n\n- Rate limits use a **sliding window algorithm** (requests per minute)\n- Limits are configured per API key\n- When exceeded, requests return `429 Too Many Requests`\n- Rate limit headers are included in all authenticated responses\n\n### Rate Limit Headers\n\n| Header | Description |\n|--------|-------------|\n| `X-RateLimit-Limit` | Maximum requests per minute |\n| `X-RateLimit-Remaining` | Remaining requests in current window |\n| `X-RateLimit-Reset` | Seconds until window resets |\n\n### Configuring Rate Limits\n\nSet rate limits when creating or updating API keys:\n\n```typescript\n// Via API (requires admin scope)\nPOST /api/api-keys\n{\n  \"name\": \"My Agent\",\n  \"scopes\": [\"request:create\", \"request:read\"],\n  \"rateLimit\": 60  // 60 requests per minute\n}\n\n// null = unlimited\n{\n  \"name\": \"Internal Service\",\n  \"scopes\": [\"admin\"],\n  \"rateLimit\": null\n}\n```\n\n### Dashboard\n\nRate limits can also be managed from the web dashboard under **Settings → API Keys**.\n\n## Webhooks\n\nAgentGate can notify external systems when request events occur.\n\n### Setting Up Webhooks\n\n```typescript\n// Create a webhook via API\nPOST /api/webhooks\n{\n  \"url\": \"https://your-server.com/webhook\",\n  \"events\": [\"request.created\", \"request.decided\"],\n  \"secret\": \"optional-signing-secret\"\n}\n```\n\n### Webhook Events\n\n| Event | Description |\n|-------|-------------|\n| `request.created` | A new approval request was created |\n| `request.decided` | A request was approved or denied |\n| `request.expired` | A request expired without decision |\n\n### Webhook Payload\n\n```json\n{\n  \"event\": \"request.decided\",\n  \"timestamp\": \"2024-01-15T10:30:00Z\",\n  \"data\": {\n    \"id\": \"abc123\",\n    \"action\": \"send_email\",\n    \"status\": \"approved\",\n    \"decidedBy\": \"admin@example.com\"\n  }\n}\n```\n\n### Webhook Signatures\n\nIf you provide a `secret`, requests are signed with HMAC-SHA256:\n\n```\nX-AgentGate-Signature: sha256=...\n```\n\nVerify by computing `HMAC-SHA256(secret, body)` and comparing.\n\n### Webhook Retry\n\nFailed 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.\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `PORT` | `3000` | Server port |\n| `DATABASE_URL` | `./data/agentgate.db` | SQLite database path |\n| `AGENTGATE_API_KEY` | - | API key for SDK/CLI |\n| `SLACK_BOT_TOKEN` | - | Slack bot token (for Slack integration) |\n| `SLACK_SIGNING_SECRET` | - | Slack signing secret |\n| `DISCORD_BOT_TOKEN` | - | Discord bot token (for Discord integration) |\n| `DISCORD_DEFAULT_CHANNEL` | - | Default Discord channel for notifications |\n\n### File-Based Secrets (`_FILE` suffix)\n\nFor 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:\n\n| Variable | Reads secret from file |\n|----------|----------------------|\n| `ADMIN_API_KEY_FILE` | Sets `ADMIN_API_KEY` |\n| `JWT_SECRET_FILE` | Sets `JWT_SECRET` |\n| `DATABASE_URL_FILE` | Sets `DATABASE_URL` |\n| `REDIS_URL_FILE` | Sets `REDIS_URL` |\n| `SLACK_BOT_TOKEN_FILE` | Sets `SLACK_BOT_TOKEN` |\n| `SLACK_SIGNING_SECRET_FILE` | Sets `SLACK_SIGNING_SECRET` |\n| `DISCORD_BOT_TOKEN_FILE` | Sets `DISCORD_BOT_TOKEN` |\n| `SMTP_PASS_FILE` | Sets `SMTP_PASS` |\n\n**Behavior:**\n- File contents are trimmed of leading/trailing whitespace\n- If both the env var and the `_FILE` variant are set, the explicit env var takes precedence\n- Missing or unreadable files produce a warning but do not crash the server\n\nExample with Docker Compose:\n\n```yaml\nservices:\n  agentgate:\n    environment:\n      ADMIN_API_KEY_FILE: /run/secrets/admin_api_key\n      JWT_SECRET_FILE: /run/secrets/jwt_secret\n    secrets:\n      - admin_api_key\n      - jwt_secret\n\nsecrets:\n  admin_api_key:\n    file: ./secrets/admin_api_key.txt\n  jwt_secret:\n    file: ./secrets/jwt_secret.txt\n```\n\n### Policy Configuration\n\nPolicies are stored in the database and can be managed via API:\n\n```typescript\n// Example: Auto-approve low-risk emails\n{\n  name: \"auto-approve-emails\",\n  priority: 10,\n  enabled: true,\n  rules: [\n    {\n      match: { action: \"send_email\" },\n      decision: \"auto_approve\"\n    }\n  ]\n}\n```\n\n## Docker Deployment\n\nAgentGate provides Docker images for easy self-hosted deployments.\n\n### Quick Start\n\n1. **Copy the example environment file:**\n\n```bash\ncp .env.example .env\n```\n\n2. **Generate secure credentials:**\n\n```bash\n# Generate admin API key (required)\necho \"ADMIN_API_KEY=$(openssl rand -hex 32)\" >> .env\n\n# Generate JWT secret (recommended for production)\necho \"JWT_SECRET=$(openssl rand -hex 32)\" >> .env\n```\n\n3. **Start all services:**\n\n```bash\ndocker-compose up -d\n```\n\n4. **Access the services:**\n\n- **Dashboard:** http://localhost:3003\n- **API Server:** http://localhost:3002\n- **Health Check:** http://localhost:3002/health\n\n> Host ports are configurable via `SERVER_PORT` (default `3002`) and `DASHBOARD_PORT` (default `3003`); both map to the container's internal port 3000/80.\n\n### Services\n\n| Service | Description | Host Port |\n|---------|-------------|------|\n| `server` | AgentGate API server | 3002 |\n| `dashboard` | Web dashboard (nginx) | 3003 |\n| `postgres` | PostgreSQL database | internal only* |\n| `redis` | Redis (rate limiting, queues) | internal only* |\n\n> \\* 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.\n\n### With Slack or Discord Bots\n\nTo include the bot services, use the `bots` profile:\n\n```bash\n# Set required bot credentials in .env first\ndocker-compose --profile bots up -d\n```\n\n### Configuration\n\nAll configuration is done via environment variables. See `.env.example` for all options.\n\n**Required variables:**\n- `ADMIN_API_KEY` — Admin API key (min 16 characters)\n\n**Recommended for production:**\n- `JWT_SECRET` — JWT signing secret (min 32 characters)\n- `CORS_ALLOWED_ORIGINS` — Restrict to your domain(s)\n- `POSTGRES_PASSWORD` — Use a strong password\n\n### Building Images\n\nBuild all images locally:\n\n```bash\ndocker-compose build\n```\n\nBuild a specific service:\n\n```bash\ndocker-compose build server\ndocker-compose build dashboard\n```\n\n### Database Migrations\n\nMigrations run automatically when the server starts. For manual control:\n\n```bash\n# Run migrations inside the container\ndocker-compose exec server node -e \"\n  import('./dist/db/migrate.js').then(m => m.runMigrations())\n\"\n```\n\n### Viewing Logs\n\n```bash\n# All services\ndocker-compose logs -f\n\n# Specific service\ndocker-compose logs -f server\n\n# Last 100 lines\ndocker-compose logs --tail=100 server\n```\n\n### Stopping Services\n\n```bash\n# Stop all\ndocker-compose down\n\n# Stop and remove volumes (WARNING: deletes data)\ndocker-compose down -v\n```\n\n### Production Considerations\n\n1. **Use a reverse proxy** (nginx, Caddy, Traefik) for TLS termination\n2. **Set strong passwords** for PostgreSQL\n3. **Restrict CORS origins** to your domain\n4. **Use Docker secrets** for sensitive values in production\n5. **Set up backups** for PostgreSQL data volume\n6. **Monitor health endpoints** for uptime checks\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Run migrations\npnpm --filter @agentkitai/agentgate-server db:migrate\n\n# Bootstrap (create admin key)\npnpm --filter @agentkitai/agentgate-server bootstrap\n\n# Start development (server + dashboard)\npnpm dev\n```\n\n### Testing\n\nAgentGate uses [Vitest](https://vitest.dev/) for testing across all packages.\n\n```bash\n# Run all tests\npnpm test\n\n# Run tests with coverage report\npnpm test:coverage\n\n# Run tests in watch mode (single package)\npnpm --filter @agentkitai/agentgate-server test:watch\n\n# Run a specific test file\npnpm --filter @agentkitai/agentgate-server test -- src/__tests__/integration.test.ts\n```\n\nCoverage reports are generated per-package and include line, branch, and function coverage.\n\n### Code Quality\n\n```bash\n# Build all packages\npnpm build\n\n# Type checking\npnpm typecheck\n\n# Lint (ESLint)\npnpm lint\n\n# Fix lint issues\npnpm lint:fix\n\n# Format code (Prettier)\npnpm format\n\n# Check formatting\npnpm format:check\n```\n\n## Project Structure\n\n```\nagentgate/\n├── packages/\n│   ├── core/           # Shared types, schemas, policy engine\n│   ├── server/         # Hono API server\n│   ├── sdk/            # TypeScript SDK\n│   ├── cli/            # Command-line interface\n│   ├── mcp/            # MCP server for Claude Desktop\n│   ├── slack/          # Slack bot\n│   ├── discord/        # Discord bot\n│   └── dashboard/      # React dashboard\n├── apps/\n│   └── demo/           # Demo application\n├── docker-compose.yml  # Docker deployment\n└── package.json        # Monorepo root\n```\n\n## Contributing\n\nContributions are welcome! To get started:\n\n1. Fork the repository\n2. Clone and install dependencies (`pnpm install`)\n3. Follow the [Development](#development) section above to set up your local environment\n4. Create a feature branch and make your changes\n5. Run `pnpm build && pnpm test` to verify everything works\n6. Open a pull request\n\nPlease make sure all tests pass and code is formatted (`pnpm format:check && pnpm lint`) before submitting.\n\n\n## 🧰 AgentKit Ecosystem\n\n| Project | Description | |\n|---------|-------------|-|\n| [AgentLens](https://github.com/agentkitai/agentlens) | Observability & audit trail for AI agents | |\n| [Lore](https://github.com/agentkitai/lore) | Cross-agent memory and lesson sharing | |\n| **AgentGate** | Human-in-the-loop approval gateway | ⬅️ you are here |\n| [FormBridge](https://github.com/agentkitai/formbridge) | Agent-human mixed-mode forms | |\n| [AgentEval](https://github.com/agentkitai/agenteval) | Testing & evaluation framework | |\n| [agentkit-cli](https://github.com/agentkitai/agentkit-cli) | Unified CLI orchestrator | |\n\n## License\n\nMIT\n",
  "bytes": 23267,
  "sha": "0e3b182ddb94742e2641ebf1f65b76c939ca04e9241ba5e671c0aeb0653fd6f8",
  "repo_slug": "agentkitai/agentgate",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_agentkitai_agentgate_124f5646/readme"
}