aic-agent — API (EN)EN

aic-agent API reference

The complete public surface. Everything below is in package aicagent (github.com/varwof/aic-agent); subpackages identity, bearer and transport are covered at the end. go doc github.com/varwof/aic-agent is the exhaustive source; this is the curated copy.

Symbols

Call Use
New(cfg Config) (*Agent, error) build an agent; returns an error on an invalid Config
LoadClientConfigFile(path) / ParseClientConfig(data) configure from a JSON file (unknown fields rejected)
(c Config) Validate() error validate a config standalone
(c Config) Authorize(opID, params) CLC pre-check against c.Capabilities
AuthorizeGrants(grants, opID, params) CLC pre-check against an explicit grant set
identity.GenerateKey / Load / ParsePEM create/load an agent key (ES256/EdDSA, P-256/Ed25519)
bearer.Sign(key, opt) mint a local aic+jwt
bearer.SignDA(opt) sign a Delegation Authorization assertion (v2, SPKI-bound by default)
(IssuerClient) Exchange(ctx, da, audience) RFC 7523 exchange at a token endpoint

Agent lifecycle

Method Behaviour
New(cfg) validates config, loads key/certs, builds transports
Close() error releases config-owned resources (log file, etc.)
(a Agent) Client() *http.Client the underlying client for code that wants the standard surface
(a Agent) Token() (string, error) the current bearer token (cached form; local mode mints per request at the transport)
(a Agent) Refresh() (string, error) force a fresh token (import for remote issuance)
(a Agent) Get(uri) / (a Agent) Do(req) one-shot calls on the credential-carrying transport
(a Agent) DoWithOptions(req, opt) Do with per-request options
(a Agent) DoAIC(req, opt) (*DoResult, error) the structured call: returns the parsed refusal and evidence-retry state

DoAIC returns a DoResult carrying Denied *RefusalError, EvidenceClosed bool and EvidenceRefused bool so callers can distinguish a plain 403 from "the evidence machine retried once" vs "a live challenge went unanswered".

AIC issuance (human-in-the-loop)

Method Behaviour
SubmitAICRequest(ctx, opt) (id string, err) enqueue the request; returns its id
WaitForAIC(ctx, opt, id, timeout, poll) poll until a human approves/rejects
GenerateCSR(key, cn) build the CSR for the agent's own key
IssueAICCertificate(ctx, opt, status, csrPEM) (*AICResult) present evidence + CSR to core; mints the cert
ObtainAIC(ctx, opt) (*AICResult) all four in sequence

AICResult carries CertPEM, KeyPEM, Serial, CA, RequestID, UserCertPEM and the effective Constraints. AICRequestOptions holds SignerURL, CoreURL, CoreToken, AgentID, PrincipalUID, Capabilities, ReasonCode, Description, LifetimeSec, DAVersion (2 = SPKI-bound, default; 1 = legacy), ValidityDays, Subject.

Refusals and challenges

RefusalError is the SDK's signature error (matchable with errors.As):

type RefusalError struct {
    Method, URL string
    Status      int
    Code        string   // compact {"code":…}
    Message     string
    // RFC 9457 problem members
    ProblemType, Title, Detail string
    Challenge          *semantics.Challenge // parsed CLC-CHALLENGE-v1 (usable)
    ChallengeUnavailable bool               // announced challenge, unusable
    HasRetryAfter  bool
    RetryAfterSec  int
    RawBody        []byte
}

Plain denial (application/json) and remediable denial (application/problem+json with a challenge member and optional Retry-After) are both parsed. allow_unresolved/challenge is not a verdict: an operation that comes back with outstanding obligations must not be treated as allowed.

The evidence machine

Config.EvidenceProvider func(ctx, ref) (ok bool, err error) is the client half of the evidence-facts mechanism. On a usable challenge the SDK: 1. rejects the retry when the challenge is stale (Challenge.Usable), 2. waits out Retry-After / retry_timing.not_before, never past expires_at, 3. asks the provider, 4. retries the byte-identical request once.

A second denial, stale/unparseable challenge, declined provider or provider error all reach the caller as-is. The SDK never transmits evidence itself — there is no wire channel for it.

DoOptions{Token, Audience, WithoutEvidenceRetry} tunes per-request behaviour.

Config (full field list)

See reference.md for the complete table with defaults; the short version by group:

  • Mode/transportMode (Bearer/MTLS), Key, Token, CertFile, KeyFile, ServerCA, Transport
  • Local mintingIssuer, Audience, Subject, Realm, ID, Capabilities, DelegationMode
  • Remote issuanceRemoteIssuer (URL), DA, UserSigner, DASignerMode ("local"/"signer"), DASigner, IssuerClientID/Secret
  • TLS for SDK-managed outboundRootCA (signer/issuer/LLM trust bundle)
  • OpsLogger, LogFile
  • EvidenceEvidenceProvider
  • LLMLLMConfig

identity subpackage

AgentKey (ES256/EdDSA): SPKI, Thumb (RFC 7638), Principal(), Cnf(), Marshal/Write/ParsePEM. GenerateKey(t), Load(path, t).

bearer subpackage

Sign(key, opt), SignDA(opt) (signed with the principal key; v2 DA binds the agent SPKI by default), SignOuter, IssuerClient.Exchange (RFC 7523; rejects non-HTTPS endpoints by default).

transport subpackage

BearerTransport (header injection, refresh provider), NewMTLSTransport (mTLS RoundTripper), TransportWithCA, PoolFromFiles, MTLSConfig.Load. BearerTransport.RoundTrip is -race clean on SetToken; the refresh path resets bodies via GetBody and only retries idempotent or replayable requests.