AI News HubLIVE
站内改写5 分钟阅读

待翻译:Show HN: AgentGate – signed receipts for AI agent SaaS actions

AI 服务暂时不可用,以下为来源摘要,待恢复后补全翻译:Uh oh! There was an error while loading. Please reload this page. Notifications You must be signed in to change notification settings Fork 0 Star 0 BranchesTags Open more actions menu Latest commit History 27 Commits 27…

来源Hacker News AI作者: goodra7174

AI 服务暂时不可用,以下为来源正文,待恢复后补全翻译。

Uh oh! There was an error while loading. Please reload this page. Notifications You must be signed in to change notification settings Fork 0 Star 0 BranchesTags Open more actions menu Latest commit History 27 Commits 27 Commits Folders and files NameName Last commit message Last commit date .github .github .planning .planning cmd cmd config config configs configs docs docs examples/basic examples/basic internal internal pkg/sdk pkg/sdk tests/integration tests/integration .env.example .env.example .gitignore .gitignore .goreleaser.yaml .goreleaser.yaml CLAUDE.md CLAUDE.md CONTRIBUTING.md CONTRIBUTING.md Dockerfile Dockerfile Dockerfile.release Dockerfile.release LICENSE LICENSE Makefile Makefile NOTICE NOTICE README.md README.md SECURITY.md SECURITY.md agentgate-agents.md agentgate-agents.md agentgate-architecture.md agentgate-architecture.md agentgate-copilot-instructions.md agentgate-copilot-instructions.md agentgate-copilot-prompt.md agentgate-copilot-prompt.md docker-compose.yaml docker-compose.yaml go.mod go.mod go.sum go.sum Repository files navigation A thin API gateway that lets AI agents call SaaS APIs (GitHub, Slack, Google Workspace) on behalf of users. Agents never see tokens — the gateway handles OAuth, encrypted token storage, and request proxying. Every action gets a signed, gap-free receipt that anyone can verify offline, without AgentGate's secret key. Quickstart Run the released image. No clone, no build, no Go toolchain — just the image published to GHCR on every tagged release: mkdir -p data docker run -d --name agentgate \ -p 8080:8080 \ -e AGENTGATE_VAULT_KEY=dev-key-change-in-production-32b \ -e AGENTGATE_ADMIN_SECRET=admin-dev-secret-change-me!! \ -v $(pwd)/data:/data \ ghcr.io/clawdlinux/agentgate:latest It bootstraps one agent API key on first boot and logs it once: docker logs agentgate | grep agent_key # {"agent_key":"ag_live_..."} — save this, it is never shown again Call an action. Without a linked account this returns token_missing — the point being that a receipt is still committed for the attempt, not just for successful calls, so the audit trail can't have quiet gaps: curl -s -X POST http://localhost:8080/v1/act \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"service":"github","action":"list_repos","on_behalf_of":"demo-user","params":{"per_page":1}}' # {"error":"no token for user demo-user on service github — user must connect their account first","code":"token_missing"} Connect a real account. Register a GitHub OAuth App once at github.com/settings/developers (callback URL http://localhost:8080/auth/callback/github), pass GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET as extra -e flags on the docker run above, then get the authorization link and open it in a browser: curl -s -X POST http://localhost:8080/admin/link \ -H "X-Admin-Secret: admin-dev-secret-change-me!!" \ -H "Content-Type: application/json" \ -d '{"user_id":"demo-user","service":"github"}' # open the returned authorize_url, click Authorize, then re-run the /v1/act call above Inspect the receipt ledger. Open http://localhost:8080/dashboard/ and enter the gateway URL, then the value of AGENTGATE_ADMIN_SECRET. The dashboard checks the visible receipt chain locally. Use the standalone verifier below for full cryptographic proof. Auditing, standalone Verification never depends on the gateway, Docker, or a Go toolchain — it reads the SQLite receipt log and a pinned trust file directly. Anyone with a copy of agentgate.db and a trust file can run this, including someone who has never seen this repo: # while the gateway is up, once: save the trust root as a local file curl -s http://localhost:8080/v1/receipts/pubkey -o trust.json # download the verifier archive matching your OS/arch from # https://github.com/Clawdlinux/agentgate/releases/latest — no other install step tar xzf agentgate___.tar.gz ./agentgate-verify --source sqlite --path ./data/agentgate.db --trust-root ./trust.json # PASS: 1 receipts verified, head seq=1 hash=... No network call happens during verification itself — trust.json is a pinned local file, and agentgate-verify only reads the local SQLite file. Pass --expected-head : (from a checkpoint recorded separately, e.g. at handoff to an auditor) to also assert completeness, not just chain integrity. For scripts, add --format json to receive one machine-readable result object while keeping the same exit codes. Add --quiet (or -q) to text output to print only the PASS: summary on successful verification. Development option To build from source instead of pulling the release image — useful when iterating on the gateway itself — docker compose still works and rebuilds the image on every up: git clone https://github.com/Clawdlinux/agentgate.git cd agentgate docker compose up -d --build It reads OAuth credentials from a .env file (see .env.example) instead of inline -e flags, and the same /v1/act and /admin/link calls above work against it unchanged. The compose image is also built FROM scratch (no shell, no package manager — see the comment in Dockerfile), so verifying "inside" the container isn't an option here either. Use the same standalone flow from the Auditing section above, pointed at compose's bind-mounted ./data/agentgate.db: curl the trust root, download or make build-verify the verifier, and run it against the host path directly. Stop and restart the container (docker compose restart agentgate) and run the verify command again — the signing identity and the receipt are still there, from the bind-mounted ./data/agentgate.db. Architecture Agent → POST /v1/act → [Auth MW] → [Registry] → [Vault: get token] → [Proxy: call upstream] → Response ┌─────────────────────────────────────────────────────┐ │ AI AGENT │ │ POST http://localhost:8080/v1/act │ │ { service, action, on_behalf_of, params } │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ AGENTGATE GATEWAY │ │ │ │ Auth MW → Registry → Vault → Proxy → Upstream │ │ Rate Limiter │ Audit Logger │ OAuth Callbacks │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ UPSTREAM SaaS APIs │ │ GitHub │ Slack │ Google Workspace │ └─────────────────────────────────────────────────────┘ API Reference POST /v1/act Execute a SaaS API action on behalf of a user. Request: { "service": "github", "action": "list_repos", "on_behalf_of": "user-42", "params": {"type": "owner", "sort": "updated"} } Headers: Authorization: Bearer Response (success): { "status": 200, "body": [{"id": 1, "name": "my-repo"}], "latency_ms": 142 } Response (error): { "error": "no token for user user-42 on service github", "code": "token_missing" } GET /v1/services List available services. GET /v1/services/{name} Describe a service and its actions. GET /healthz Health check endpoint. Admin Endpoints All admin endpoints require X-Admin-Secret header. POST /admin/keys Create a new agent API key. {"name": "my-agent", "allowed_services": ["github", "slack"], "allowed_users": ["user-42"]} DELETE /admin/keys/{id} Revoke an API key. POST /admin/link Get OAuth authorization URL for user account linking. {"user_id": "user-42", "service": "github"} POST /admin/tokens Connect a bearer token for Slack, Stripe, or Calendly. The token is encrypted in the vault and never returned. {"user_id": "user-42", "service": "stripe", "access_token": ""} GET /admin/tokens/{user_id} List linked services for a user (no token values exposed). OAuth Callback GET /auth/callback/{service} OAuth redirect handler — exchanges code for tokens, stores encrypted in vault. Go SDK import "github.com/Clawdlinux/agentgate/pkg/sdk" client := sdk.NewClient("http://localhost:8080", "ag_live_...") // Call any service resp, err := client.Act(ctx, sdk.ActRequest{ Service: "github", Action: "list_repos", OnBehalfOf: "user-42", }) // Convenience helpers resp, err := client.GitHub(ctx, "user-42", "list_repos", nil) resp, err := client.Slack(ctx, "user-42", "post_message", map[string]interface{}{"channel": "#general", "text": "Hello"}) resp, err := client.Act(ctx, sdk.ActRequest{Service: "google_workspace", Action: "list_labels", OnBehalfOf: "user-42"}) // Stripe remains fully functional though unfeatured at launch: resp, err := client.Stripe(ctx, "user-42", "list_invoices", map[string]interface{}{"limit": 10}) // Error handling if sdk.IsTokenMissing(err) { // User needs to link their account } if sdk.IsRateLimited(err) { // Back off and retry } Security Model Agent keys are scoped (service × user). Agents can only access what's explicitly granted. Tokens encrypted at rest. AES-256-GCM with 32-byte key from environment. No token exposure. Agents never see OAuth tokens — only the gateway touches them. Signed receipts. Every authenticated action attempt commits one Ed25519-signed, hash-chained receipt before the response is returned — verify offline with agentgate-verify, no gateway state or private key needed. Rate limiting. Per-(agent, service) token bucket prevents runaway API usage. OAuth state encrypted with AES-256-GCM and expires after 10 minutes. OAuth refresh. Configured OAuth providers refresh tokens expiring within 5 minutes before dispatch. A failed refresh returns token_expired without calling the SaaS API. Configuration Environment Variables Variable Description Required AGENTGATE_VAULT_KEY 32-byte encryption key for the token vault and the receipt signing key Yes AGENTGATE_ADMIN_SECRET Secret for admin API access Yes AGENTGATE_PUBLIC_URL Base URL used to build the OAuth callback (default http://localhost:8080) No GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET GitHub OAuth credentials For GitHub OAuth SLACK_CLIENT_ID / SLACK_CLIENT_SECRET Slack OAuth credentials For Slack OAuth GOOGLE_WORKSPACE_CLIENT_ID / GOOGLE_WORKSPACE_CLIENT_SECRET Google OAuth credentials, requesting only the narrow gmail.labels scope For Google Workspace OAuth STRIPE_CLIENT_ID / STRIPE_CLIENT_SECRET Stripe OAuth credentials (Stripe remains configured and functional, just not a featured launch connector) For Stripe OAuth Agent API keys are bootstrapped automatically on first boot and logged once — there is no env var for a pre-supplied key (they are bcrypt-hashed in SQLite; see POST /admin/keys to create more). Service Configs Service configurations are YAML files in configs/services/. See configs/services/google_workspace.yaml for an example. The gateway itself loads the merged configs/services.yaml. Tech Stack Go 1.22+ — single binary, no runtime dependencies SQLite — embedded database for keys, tokens, audit log AES-256-GCM — token encryption at rest bcrypt — API key hashing Docker — containerized deployment Development # Build make build # Run tests make test # Run locally make run # Lint make lint Contributing Contributions are welcome. See CONTRIBUTING.md for prerequisites, build/test/lint instructions, focused pull request guidance, and DCO sign-off. Issues labeled good first issue are scoped to be independently testable without needing secrets or maintainer context. License AgentGate is licensed under the Apache License 2.0. See LICENSE. Topics Resources Readme License Contributing Contributing Security policy Security policy Activity Custom properties Stars 0 stars Watchers 0 watching Forks 0 forks Report repository