Agent¶
A self-hosted agent is its own agent provider (bootstrap ยง4.3): it holds a
key, mints its own agent tokens, and serves /.well-known/aauth-agent.json
and its JWKS (Agent.JWKS) at its issuer. Wrap an http.Client with
Transport and AAuth disappears from application code:
id, err := aauth.ParseAgentIdentifier("aauth:assistant@agent.example")
if err != nil {
return err
}
agent, err := aauth.NewAgent(id,
aauth.WithIssuer("https://agent.example"), // serves aauth-agent.json and the JWKS
aauth.WithPersonServer("https://ps.example"), // the ps claim
)
if err != nil {
return err
}
ps := aauth.NewPSClient("https://ps.example", agent)
if _, err := ps.Discover(ctx); err != nil { // endpoints from aauth-person.json
return err
}
hc := &http.Client{Transport: aauth.NewTransport(agent, ps)}
res, err := hc.Get("https://files.example/files")
For each request the transport signs with the agent's key and answers
requirement=agent-token, person-token, and auth-token challenges (401,
or a 202 deferred delivery): it obtains a person token, redeems the resource
token at the PS, verifies what it receives, caches tokens per resource with a
five-minute refresh margin, and retries. Set Transport.OnRequirement to
show the user an interaction URL and code while a request waits for them.
An agent whose tokens come from a hosted provider uses
aauth.WithTokenSource, for example with agentprovider.Client.TokenSource.
Governance is optional and uses the same client:
m, err := ps.ProposeMission(ctx, aauth.MissionProposal{
Description: "Reconcile the March invoices",
Resources: []string{"https://ledger.example"},
})
if err != nil {
return err
}
tr := aauth.NewTransport(agent, ps)
tr.MissionS256 = m.S256 // person and auth tokens are requested under the mission
perm, err := ps.RequestPermission(ctx, aauth.PermissionRequest{
Action: "SendEmail",
Description: "email the reconciliation summary",
MissionS256: m.S256,
})
if err != nil {
return err // a *aauth.MissionStatusError once the mission is terminated
}
if !perm.Granted() {
return errors.New(perm.Reason)
}