# SentryAgent.ai AgentIdP — Go SDK Official Go client for the [SentryAgent.ai AgentIdP](https://sentryagent.ai) — an open-source Identity Provider for AI agents built on OAuth 2.0 (RFC 6749) and aligned with the [AGNTCY](https://agntcy.org) open standard. ## Requirements - Go 1.21+ - A running AgentIdP server ## Installation ```bash go get github.com/sentryagent/idp-sdk-go ``` ## Quick Start ```go package main import ( "context" "fmt" "log" agentidp "github.com/sentryagent/idp-sdk-go" ) func main() { ctx := context.Background() client := agentidp.NewAgentIdPClient(agentidp.AgentIdPClientConfig{ BaseURL: "https://idp.example.com", ClientID: "your-agent-client-id", ClientSecret: "sk_live_...", }) // Register a new AI agent agent, err := client.Agents.RegisterAgent(ctx, agentidp.RegisterAgentRequest{ Email: "screener@example.com", AgentType: "screener", Version: "1.0.0", Capabilities: []string{"read", "classify"}, Owner: "platform-team", DeploymentEnv: "production", }) if err != nil { log.Fatal(err) } fmt.Printf("Registered agent: %s\n", agent.AgentID) } ``` ## Authentication The SDK handles OAuth 2.0 Client Credentials automatically. Tokens are cached and refreshed 60 seconds before expiry. All operations are goroutine-safe. ```go client := agentidp.NewAgentIdPClient(agentidp.AgentIdPClientConfig{ BaseURL: "https://idp.example.com", ClientID: "my-client-id", ClientSecret: "my-client-secret", Scope: "agents:read agents:write", // optional, defaults to all four scopes }) ``` ## Agent Registry ```go ctx := context.Background() // Register agent, err := client.Agents.RegisterAgent(ctx, agentidp.RegisterAgentRequest{...}) // List (with optional filters) agents, err := client.Agents.ListAgents(ctx, &agentidp.ListAgentsParams{ Status: "active", AgentType: "screener", Page: 1, Limit: 20, }) // Get by ID agent, err := client.Agents.GetAgent(ctx, "agent-uuid") // Partial update version := "2.0.0" agent, err := client.Agents.UpdateAgent(ctx, "agent-uuid", agentidp.UpdateAgentRequest{ Version: &version, }) // Decommission (permanent) err = client.Agents.DecommissionAgent(ctx, "agent-uuid") ``` ## Credential Management ```go // Generate (returns one-time ClientSecret) cred, err := client.Credentials.GenerateCredential(ctx, "agent-uuid") fmt.Println(cred.ClientSecret) // store this — it is never shown again // List creds, err := client.Credentials.ListCredentials(ctx, "agent-uuid", 1, 20) // Rotate (old secret is immediately invalidated) newCred, err := client.Credentials.RotateCredential(ctx, "agent-uuid", "cred-uuid") // Revoke revoked, err := client.Credentials.RevokeCredential(ctx, "agent-uuid", "cred-uuid") ``` ## Token Operations ```go // Introspect (RFC 7662) result, err := client.Tokens.IntrospectToken(ctx, "access-token-to-check") if result.Active { fmt.Printf("Token belongs to: %s\n", *result.Sub) } // Revoke err = client.Tokens.RevokeToken(ctx, "access-token-to-revoke") ``` ## Audit Log ```go // Query with filters events, err := client.Audit.QueryAuditLog(ctx, &agentidp.QueryAuditParams{ AgentID: "agent-uuid", Action: "token.issued", Outcome: "success", FromDate: "2026-01-01", ToDate: "2026-01-31", Page: 1, Limit: 50, }) // Get single event event, err := client.Audit.GetAuditEvent(ctx, "event-uuid") ``` ## Error Handling All errors are returned as `*AgentIdPError`: ```go agent, err := client.Agents.GetAgent(ctx, "unknown-id") if err != nil { if apiErr, ok := err.(*agentidp.AgentIdPError); ok { fmt.Printf("code=%s status=%d\n", apiErr.Code, apiErr.HTTPStatus) // e.g. code=AgentNotFoundError status=404 } return err } ``` | Field | Type | Description | |--------------|--------------------------|-------------------------------------------------| | `Code` | `string` | Machine-readable error code | | `Message` | `string` | Human-readable description | | `HTTPStatus` | `int` | HTTP status code (0 for network/build errors) | | `Details` | `map[string]interface{}` | Optional structured context from the API | ## Custom HTTP Client Inject a custom `*http.Client` for proxy support, custom timeouts, or test mocking: ```go client := agentidp.NewAgentIdPClient(agentidp.AgentIdPClientConfig{ BaseURL: "https://idp.example.com", ClientID: "cid", ClientSecret: "secret", HTTPClient: &http.Client{Timeout: 5 * time.Second}, }) ``` ## API Coverage | Endpoint | Method | SDK Method | |--------------------------------------------------|--------|-----------------------------------------| | POST /api/v1/agents | POST | `Agents.RegisterAgent` | | GET /api/v1/agents | GET | `Agents.ListAgents` | | GET /api/v1/agents/:id | GET | `Agents.GetAgent` | | PATCH /api/v1/agents/:id | PATCH | `Agents.UpdateAgent` | | DELETE /api/v1/agents/:id | DELETE | `Agents.DecommissionAgent` | | POST /api/v1/agents/:id/credentials | POST | `Credentials.GenerateCredential` | | GET /api/v1/agents/:id/credentials | GET | `Credentials.ListCredentials` | | POST /api/v1/agents/:id/credentials/:cid/rotate | POST | `Credentials.RotateCredential` | | DELETE /api/v1/agents/:id/credentials/:cid | DELETE | `Credentials.RevokeCredential` | | POST /api/v1/token | POST | (TokenManager — automatic) | | POST /api/v1/token/introspect | POST | `Tokens.IntrospectToken` | | POST /api/v1/token/revoke | POST | `Tokens.RevokeToken` | | GET /api/v1/audit | GET | `Audit.QueryAuditLog` | | GET /api/v1/audit/:id | GET | `Audit.GetAuditEvent` | ## License Apache 2.0 — see [LICENSE](../LICENSE).