AAuth Quickstart — CrewAI
Wire AAuth (the agent identity protocol: an agent proves who it is by signing each request with its own private key instead of sending a shared secret) into a CrewAI agent so every tool call carries a cryptographically signed identity. The agent's identity is an Ed25519 key pair registered with LumoAuth; tokens are obtained via the AAuth token endpoint; every API call goes out as a signed HTTP request (the signed request components give a per-request, replay-proof proof that the agent holds its key).
- A LumoAuth organization (agent identity is available on every plan, nothing to switch on)
- Python 3.9+
Complete Steps 1–3 first (generate a key pair, register the agent and the resource), and ideally verify with the Python SDK quickstart before wiring CrewAI.
Install
pip install 'lumoauth[aauth]' crewai crewai-tools
Example
from crewai import Agent, Task, Crew
from crewai.tools import tool
from lumoauth import AAuthClient
# 1. Initialize the AAuth client
private_pem, jwks = AAuthClient.generate_keypair()
aauth = AAuthClient(
agent_identifier="https://my-agent.example.com",
private_key_pem=private_pem,
org_id="acme-corp",
)
# 2. Obtain tokens upfront (see the AAuth Quickstart).
# agent_token is mandatory: the /agent/token endpoint authenticates the
# agent via the Agent-Auth header, so request_authorization requires it.
agent_token = "..." # your `agent+jwt`, bound to this key pair via cnf.jwk
resource_token = "..." # from your resource server
tokens = aauth.request_authorization(
resource_token=resource_token,
scope="read write",
agent_token=agent_token,
)
if tokens.get("authorization_required"):
raise RuntimeError("User consent required - implement OAuth redirect flow first")
# On success the token endpoint returns the agent access token under the
# key "auth_token" (not "access_token").
ACCESS_TOKEN = tokens["auth_token"]
# 3. Define tools that make AAuth-signed API calls
@tool
def fetch_financial_report(quarter: str) -> str:
"""Fetch a quarterly financial report from the protected API."""
resp = aauth.signed_request(
"GET",
f"https://api.example.com/v1/reports/{quarter}",
auth_token=ACCESS_TOKEN,
)
if resp.status_code == 200:
return resp.text
return f"Error: HTTP {resp.status_code}"
@tool
def submit_analysis(summary: str) -> str:
"""Submit a financial analysis to the protected API."""
resp = aauth.signed_request(
"POST",
"https://api.example.com/v1/analyses",
auth_token=ACCESS_TOKEN,
data={"summary": summary},
)
if resp.status_code in (200, 201):
return "Analysis submitted successfully."
return f"Error: HTTP {resp.status_code}"
# 4. Set up and run the CrewAI crew
analyst = Agent(
role="Financial Analyst",
goal="Retrieve Q4 financial data and submit a concise analysis",
backstory="You are an expert financial analyst with access to protected APIs.",
tools=[fetch_financial_report, submit_analysis],
verbose=True,
)
analysis_task = Task(
description="Fetch the Q4-2024 financial report and submit a two-sentence analysis.",
expected_output="Confirmation that the analysis was submitted.",
agent=analyst,
)
crew = Crew(agents=[analyst], tasks=[analysis_task], verbose=True)
result = crew.kickoff()
print(result)
How it works
| Component | Role |
|---|---|
AAuthClient | Manages key material and handles AAuth token exchange |
aauth.signed_request(...) | Adds the Signature/Signature-Input request-signature headers and the Authorization header to every API call |
ACCESS_TOKEN | Short-lived token issued after validating agent + resource identities |
| CrewAI Crew | Orchestrates agents and tasks; AAuth handles auth transparently |
The agent's identity is the Ed25519 key registered with LumoAuth. The token is fetched once via request_authorization; each tool call signs the HTTP request with aauth.signed_request, which adds the Signature/Signature-Input headers and Authorization: Bearer <access_token>.
Next steps
- AAuth Protocol spec — full protocol details
- JIT Permissions – CrewAI — add per-operation permission escalation
Standards used on this page
| Plain name | Standard |
|---|---|
| Signed HTTP requests (HTTP message signatures) | RFC 9421 |
See the standards reference for what each one covers and how LumoAuth uses it.