draco-toolkit
Authentication and authorization for AI agents: SPIFFE identity, per-tool OAuth tokens via RFC 8693 exchange, per-call authorization against OpenFGA or local policy bundles, posture management, and behavioral telemetry.
Install
pip install draco-toolkit
The distribution is draco-toolkit; the import name is draco:
from draco.core.bootstrap import bootstrap
Optional extras: pip install "draco-toolkit[metrics]" for OpenTelemetry instrumentation.
Full documentation, concepts, and guides: github.com/Draco-Tech-ai/draco-toolkit. Website: draco-tech.ai.
Developing from source
uv pip install -e ".[dev]"
Test
pytest
Lint
ruff check .
ruff format --check .
mypy src/
Configuration
The SDK reads a JSON config file via bootstrap(Mode.DIRECT, path). All IdP-specific behavior is controlled by config fields; the code has no IdP-specific branches.
Token flow
The SDK uses a two-phase token model:
- Base token: SVID assertion at the IdP's token endpoint. The grant type and parameter names vary by IdP.
- Per-target tokens: RFC 8693 token exchange of the base token, scoped by audience.
DCR (RFC 7591) is optional. When configured, the agent self-registers with the IdP at startup and deregisters on shutdown. When not configured, the agent uses a pre-registered client identified by the SVID's subject claim.
Keycloak
Keycloak uses client_credentials grant with the SVID as a client_assertion (federated-jwt client authentication). DCR is not supported directly with SVIDs; agents use pre-registered clients.
{
"agent_spiffe_id": "spiffe://example.draco.local/agents/hello-agent/default",
"spiffe_endpoint_socket": "unix:///spiffe-workload-api/spire-agent.sock",
"idp_token_endpoint": "https://keycloak.example.draco.local/realms/draco/protocol/openid-connect/token",
"idp_grant_type": "client_credentials",
"ca_bundle_path": "/etc/ssl/step-ca/root_ca.crt",
"authz_backend": "openfga",
"openfga_url": "https://openfga.example.draco.local",
"openfga_store_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"openfga_audience": "openfga",
"posture_source": "/etc/draco/bundles",
"trust_store_backend": "file",
"trust_store_path": "/var/draco/trust-state.json",
"tools": [...]
}
Keycloak prerequisites:
- A Keycloak client (e.g.
draco-hello-agent) withclientAuthenticatorType=federated-jwt,serviceAccountsEnabled=true, andstandard.token.exchange.enabled=true. jwt.credential.subset to the agent's SPIFFE ID.jwt.credential.issuerset to the SPIFFE IdP alias (e.g.spire).- A SPIFFE identity provider at the realm level with the SPIRE trust domain and bundle endpoint.
- For each target service (e.g. OpenFGA), a Keycloak client registered with that service name as the
clientId, and the requesting client's service account assigned a role on that target client (Keycloak resolves available exchange audiences via role mappings). - A self-audience mapper on the agent's client so the base token's
audincludes the client itself (required by Keycloak's standard token exchange).
Other RFC 8693-capable IdPs are supported through the same configuration surface (idp_grant_type, idp_client_audience, and the optional dcr block); Keycloak is the documented reference.
Config field reference
| Field | Required | Default | Description |
|---|---|---|---|
agent_spiffe_id |
yes | The agent's SPIFFE ID. | |
spiffe_endpoint_socket |
yes | Path to the SPIRE Workload API socket. | |
idp_token_endpoint |
yes | OAuth token endpoint URL. | |
idp_grant_type |
no | client_credentials |
Grant type for the base token. client_credentials (Keycloak federated-jwt), or urn:ietf:params:oauth:grant-type:jwt-bearer for IdPs that take the SVID as the authorization grant. |
idp_assertion_type |
no | urn:ietf:params:oauth:client-assertion-type:jwt-spiffe |
Client assertion type. |
idp_client_audience |
no | derived from token endpoint | Audience for the client_assertion SVID. Omit for Keycloak (derived from realm URL); set explicitly when the IdP expects a fixed audience string. |
ca_bundle_path |
no | CA bundle for TLS verification to the IdP. | |
authz_backend |
yes | openfga for live authz, bundle for local-only. |
|
openfga_url |
when openfga | OpenFGA API URL. | |
openfga_store_id |
when openfga | OpenFGA store ID. | |
openfga_audience |
no | openfga_url |
Audience for RFC 8693 exchange when targeting OpenFGA. Set to the Keycloak client_id for OpenFGA (e.g. openfga). |
posture_source |
yes | Path to the directory containing per-trust-level bundle JSON files. | |
trust_store_backend |
no | file |
file or openbao. |
trust_store_path |
when file | Path to the trust state JSON file. | |
dcr |
no | DCR configuration. Omit to skip DCR (pre-registered client). | |
dcr.auth_method |
no | private_key_jwt |
token_endpoint_auth_method declared to the IdP during DCR. |
dcr.grant_types |
no | [client_credentials, token-exchange] |
Grant types requested during DCR. |
dcr.jwks_uri |
no | SPIRE OIDC JWKS URL, included in the DCR body so the IdP can verify the client's assertions. | |
dcr.scopes_source |
no | policy |
Where to derive scopes for DCR. |
tools |
no | Array of tool definitions (name, description, parameters, endpoint, transport). |
Metadata
Release files for draco-toolkit 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| draco_toolkit-0.1.2.tar.gz | 195.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| draco_toolkit-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 261.2 kB
Release files / draco_toolkit-0.1.2.tar.gz
| Download URL | draco_toolkit-0.1.2.tar.gz |
|---|---|
| Size | 195.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
52735d6cb8c7886313dbf91570c201a68621a9a6a04493b59690ff75745a40d4
|
|
BLAKE2b-256 checksum How to use checksums |
7173d439deaaf1a4d1a2f4f83d4ac9ec03960d270c5babfaf3a57181fb273366
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / draco_toolkit-0.1.2-py3-none-any.whl
| Download URL | draco_toolkit-0.1.2-py3-none-any.whl |
|---|---|
| Size | 65.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4ebca9f6814c80f8a6e965bb8756fd1982897eff6a4324a22cc5181bb91e5eb6
|
|
BLAKE2b-256 checksum How to use checksums |
60005ebe43f780cbb67e8698c778787ebdcf330b887615364dd7a7d76427177c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|