Single-package agentidp SDK in sdk-go/: - AgentIdPClient composing AgentRegistryClient, CredentialClient, TokenServiceClient, AuditClient — all 14 endpoints covered - Goroutine-safe TokenManager (sync.Mutex) with 60s refresh buffer - AgentIdPError implementing error interface with Code/HTTPStatus/Details - Context-aware: all service methods take context.Context as first arg - doRequest shared helper; token endpoints use form-encoded POST directly - go vet: 0 warnings | staticcheck: 0 warnings - go test ./...: 37/37 passed | coverage: 81.0% (>80% gate) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.4 KiB
6.4 KiB
SentryAgent.ai AgentIdP — Go SDK
Official Go client for the SentryAgent.ai AgentIdP — an open-source Identity Provider for AI agents built on OAuth 2.0 (RFC 6749) and aligned with the AGNTCY open standard.
Requirements
- Go 1.21+
- A running AgentIdP server
Installation
go get github.com/sentryagent/idp-sdk-go
Quick Start
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.
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
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
// 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
// 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
// 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:
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:
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.