The Python SDK provides sync and async clients for the AgentFlow API.
Installation
uv add agentflow --default-index https://<package-index>/simple/
# or
python -m pip install --index-url https://<package-index>/simple/ agentflow
The public PyPI package named agentflow is not the private AgentFlow SDK
unless your organization has published it there. Use your onboarding package
source, private package index, or internal wheel.
Authenticate
Create a profile with the CLI:
agentflow login \
--endpoint https://api.example.com \
--profile prod \
--method device \
--client-id <auth0-client-id> \
--audience <auth0-api-audience> \
--auth0-domain <auth0-domain>
Use --method m2m for service clients and --method dev for local backends
started with DEV_AUTH_BYPASS=true.
Initialize from a profile
from agentflow import AgentFlow
client = AgentFlow.from_profile("prod")
If you already have a bearer token, pass it directly or set environment
variables:
from agentflow import AgentFlow
client = AgentFlow(endpoint="https://api.example.com", access_token="<agentflow-access-token>")
export AGENTFLOW_ENDPOINT=https://api.example.com
export AGENTFLOW_ACCESS_TOKEN=<agentflow-access-token>
For machine-to-machine clients that act on behalf of a user, pass scope="agentflow:conversations agentflow:cancellations" when constructing the client, set AGENTFLOW_SCOPE for environment-configured clients, or add the same scope to a saved M2M profile.
Agents
Chat
from agentflow import AgentFlow
with AgentFlow.from_profile("prod") as client:
agent_id = client.agents.by_name("MainAgent").id
response = client.agents.run(agent_id=agent_id, message="What can you do?")
print(response.text)
Stream
import asyncio
from agentflow import AsyncAgentFlow
from agentflow.events import TextDelta
async def main():
async with AsyncAgentFlow.from_profile("prod") as client:
agent_id = (await client.agents.by_name("MainAgent")).id
async for event in client.agents.stream(agent_id=agent_id, message="Hello"):
if isinstance(event, TextDelta):
print(event.text, end="", flush=True)
asyncio.run(main())
Chat with conversation context
from agentflow import AsyncAgentFlow
async with AsyncAgentFlow.from_profile("local") as client:
agent_id = {agent.name: agent.id for agent in await client.agents.list()}["MainAgent"]
conversation = await client.conversations.create(agent_id=agent_id)
await conversation.send("Show me the pipeline")
response = await conversation.send("Follow up on the last topic")
Knowledge Bases
Search
from agentflow import AsyncAgentFlow
async with AsyncAgentFlow.from_profile("local") as client:
results = await client.knowledge_bases.search(
"550e8400-e29b-41d4-a716-446655440000",
query="How does billing work?",
limit=5,
)
for result in results.documents:
print(result.content)
Completions and Batches
Use client.completions for sync inline completion helpers and client.batches for async batch jobs.
import time
from agentflow import AgentFlow
with AgentFlow.from_profile("prod") as client:
labels = client.completions.classify(
items=[{"content": "Great product, slow delivery."}],
categories=["positive", "negative", "mixed"],
)
print(labels.results[0]["result"])
batch = client.batches.submit(
operation="extract",
items=[{"content": "Sarah Chen, VP Engineering at Acme Corp, wants 500 seats by Q3."}],
extraction_instructions="Extract contact, title, company, seat_count, and timeline.",
)
print(batch.id, batch.status)
while batch.status not in {"completed", "failed", "cancelled"}:
time.sleep(2)
batch = client.batches.retrieve(batch.id)
page = client.batches.output(batch.id, format="json", offset=0, limit=1000)
for row in page.results:
print(row["result"])
BYO LLM Admin
Admins can manage encrypted tenant provider keys and model policy through client.models.
from agentflow import AgentFlow
with AgentFlow.from_profile("admin") as client:
options = client.models.model_options()
print(options.use_cases)
client.models.save_configuration(
provider="anthropic",
api_key="sk-ant-...",
allowed_models=[
"anthropic/claude-haiku-4-5-20251101",
"anthropic/claude-sonnet-4-5-20250929",
],
default_models={
"chat": "anthropic/claude-sonnet-4-5-20250929",
"tool": "anthropic/claude-haiku-4-5-20251101",
"title": "anthropic/claude-haiku-4-5-20251101",
"enrichment": "anthropic/claude-haiku-4-5-20251101",
},
)
client.models.save_configuration(
provider="google",
api_key="AIza...",
allowed_models=["google/gemini-2.5-flash"],
default_models={
"follow_up_questions": "google/gemini-2.5-flash",
"autocomplete": "google/gemini-2.5-flash",
},
)
policy = client.models.configurations()
print(policy.mode, policy.allowed_models)
Secrets are never returned by the SDK. Provider configurations expose only metadata such as key_last_four, allowed_models, and default_models.
Conversations
List
conversations = client.conversations.list()
Search
matches = client.conversations.search("Acme renewal")
Get messages
conversation = client.conversations.retrieve("conv_abc123")
for msg in conversation.messages:
print(msg.role, msg.content)
Memory
from agentflow import MemoryPolicy, RunOptions
core = client.memory.get("core")
client.memory.update(
"core",
"- Prefers concise answers",
expected_updated_at=core.updated_at.isoformat(),
)
for match in client.memory.recall("Acme renewal"):
print(match.scope, match.content)
result = client.agents.run(
agent_id="agent_records",
message="What changed with Acme?",
options=RunOptions(memory_policy=MemoryPolicy(archival_mode="auto", archival_limit=5)),
)
System
Health check
status = client.system.health()
print(status)