Python SDK
Everything you need to build, run, and refine agents from Python.
Installation
pip install flymyai
Requires Python 3.8+. The agents module ships inside the flymyai package.
30-second example
from flymyai import AgentClient
client = AgentClient(api_key="fly-***")
# 1. Add a tool
tool = client.tools.create(mcp_tool="tavily")
# 2. Create an agent
agent = client.agents.create(
name="Web Researcher",
goal="Search the web for {{ topic }} and return a concise summary with sources.",
tools=[tool.id],
)
# 3. Run & wait
run = client.runs.create(agent_id=agent.id)
result = client.runs.wait(run.id)
print(result.output)
Client
- Sync
- Async
from flymyai import AgentClient
client = AgentClient(
api_key="fly-***", # or set FLYMYAI_API_KEY env var
base_url="...", # default: https://backend.flymy.ai
timeout=60.0, # request timeout in seconds
)
from flymyai import AsyncAgentClient
async with AsyncAgentClient(api_key="fly-***") as client:
agent = await client.agents.create(name="Bot", goal="Help users")
run = await client.runs.create(agent_id=agent.id)
result = await client.runs.wait(run.id)
| Env variable | Description | Default |
|---|---|---|
FLYMYAI_API_KEY | API key (used when api_key is omitted) | — |
FLYMYAI_DSN | Base URL override | https://backend.flymy.ai |
The client exposes four resource namespaces:
| Namespace | What it does |
|---|---|
client.agents | Create, list, update, delete, and run agents |
client.runs | Start runs, poll for results, stream events, follow up |
client.tools | Browse the tool catalog, add and configure MCP tools |
client.compilations | Compile agent runs into standalone scripts |
client.agents
Create
agent = client.agents.create(
name="Lead Profiler",
goal="""Research {{ name }} at {{ company }}.
Return background, recent initiatives, and recommended outreach angle.""",
tools=[web_search_id, browse_id], # tool IDs (integers)
)
print(agent.id) # UUID string
print(agent.goal) # alias for user_prompt
print(agent.status) # "draft"
| Parameter | Type | Required | Description |
|---|---|---|---|
name | str | Yes | Human-readable name |
goal | str | Yes | Instructions (supports Handlebars templating) |
tools | list[int] | No | Tool IDs to attach |
status | str | No | draft (default) or active |
List / Get / Update / Delete
# List all agents
agents = client.agents.list()
# Get with full details (nested tool objects)
agent = client.agents.get("a1b2c3d4-...")
# Partial update — only send the fields you want to change
agent = client.agents.update("a1b2c3d4-...",
goal="Updated instructions.",
)
# Soft-delete (archive)
client.agents.delete("a1b2c3d4-...")
Run
Start the agent loop. Returns immediately — the agent executes asynchronously on the server.
run = client.agents.run("a1b2c3d4-...")
print(run.id) # execution ID (int)
print(run.status) # "pending" or "running"
client.runs.create(agent_id=...) is an alias for client.agents.run(...). Use whichever reads better in your code.
client.runs
Create a run
run = client.runs.create(agent_id=agent.id)
Get run details
run = client.runs.get(42)
print(run.status) # "completed"
print(run.output) # the agent's result (dict)
print(run.error) # None or error message
for log in run.logs:
print(f"[{log.type}] {log.message}")
Wait for completion
Polls the server until the run finishes. Returns the final RunDetail.
result = client.runs.wait(run.id, timeout=300, poll_interval=2.0)
if result.status == "completed":
print(result.output)
else:
print(f"Run ended with status: {result.status}")
print(f"Error: {result.error}")
Raises TimeoutError if the run doesn't finish in time.
Stream events
Watch execution step-by-step. Yields ExecutionLog objects as they appear.
run = client.runs.create(agent_id=agent.id)
for event in client.runs.stream_events(run.id, timeout=600):
if event.type == "tool_called":
print(f" Tool: {event.message}")
elif event.type == "tool_call_exception":
print(f" Error: {event.message}")
else:
print(f" [{event.type}] {event.message}")
Event types:
| Type | Meaning |
|---|---|
declared_functions | Agent declared the tools it will use |
tool_called | A tool was invoked |
tool_call_exception | A tool call failed |
task_cancelled | The run was cancelled |
Cancel
client.runs.cancel(42)
Follow up
Append a user message and restart the agent loop on the same execution:
run = client.runs.append_message(run.id, text="Also check their LinkedIn profile.")
result = client.runs.wait(run.id)
client.tools
Tools are MCP integrations available on the FlyMy.AI platform. You configure them once, then attach to any agent.
Browse the catalog
catalog = client.tools.available()
for t in catalog:
print(f"{t.name:20s} {t.type:15s} {t.title}")
# github composio Github
# tavily custom_class Tavily
# telegram-mcp oauth Telegram Mcp
Add and configure a tool
# Add
tool = client.tools.create(mcp_tool="github")
print(tool.is_configured) # False
# Walk through configuration steps
while not tool.is_configured:
step = tool.next_configuration_step
if not step:
break
print(f"Step: {step['description']}")
# → "Provide your GitHub token"
tool = client.tools.provide_config(
tool.id,
user_response={"GITHUB_TOKEN": "ghp_..."},
)
print(tool.is_configured) # True
Call a tool directly
For custom_class tools, you can invoke actions without running a full agent:
result = client.tools.call(
tool.id,
action="search",
arguments={"query": "FlyMyAI agents"},
)
print(result)
Other operations
tools = client.tools.list() # your configured tools
tool = client.tools.get(7) # by ID
tool = client.tools.update(7, user_config={"key": "new_value"}) # merge config
client.tools.delete(7) # remove
client.compilations
Turn a successful agent run into a standalone Python script.
# Compile
compilation = client.compilations.compile(execution_id=run.id)
# Wait for compilation (poll)
import time
while compilation.status in ("pending", "compiling"):
time.sleep(2)
compilation = client.compilations.get(compilation.id)
print(compilation.script_code) # generated Python
# Execute
result = client.compilations.run(compilation.id)
Training with patches
Improve your agent iteratively by evaluating output and patching its configuration.
Refine the goal
run = client.runs.create(agent_id=agent.id)
result = client.runs.wait(run.id)
# Output too verbose? Patch the instructions
client.agents.update(agent.id,
goal="Research {{ topic }}. Be concise: max 3 paragraphs, bullet points preferred.",
)
Automated training loop
for i in range(5):
run = client.runs.create(agent_id=agent.id)
result = client.runs.wait(run.id)
score = evaluate(result.output) # your scoring function
if score >= 0.8:
break
See the Training with Patches guide for detailed patterns.
Async usage
Every method has an async counterpart:
import asyncio
from flymyai import AsyncAgentClient
async def main():
async with AsyncAgentClient(api_key="fly-***") as client:
agent = await client.agents.create(
name="Researcher",
goal="Find info about {{ topic }}.",
)
run = await client.runs.create(agent_id=agent.id)
# Stream events
async for event in client.runs.stream_events(run.id):
print(f"[{event.type}] {event.message}")
result = await client.runs.get(run.id)
print(result.output)
asyncio.run(main())
Complete example
End-to-end: set up tools, create agent, run, stream, follow up, train.
from flymyai import AgentClient
client = AgentClient(api_key="fly-***")
# ── 1. Set up tools ─────────────────────────────────────────────
catalog = client.tools.available()
print("Available:", [t.name for t in catalog])
tool = client.tools.create(mcp_tool="tavily")
tool = client.tools.provide_config(
tool.id,
user_response={"TAVILY_API_KEY": "tvly-..."},
)
# ── 2. Create agent ─────────────────────────────────────────────
agent = client.agents.create(
name="Research Assistant",
goal="Research {{ topic }} thoroughly. Return a summary with key findings and sources.",
tools=[tool.id],
)
# ── 3. Run & stream ─────────────────────────────────────────────
run = client.runs.create(agent_id=agent.id)
print(f"Run {run.id} started")
for event in client.runs.stream_events(run.id, timeout=600):
print(f" [{event.type}] {event.message}")
# ── 4. Get result ────────────────────────────────────────────────
result = client.runs.get(run.id)
if result.status == "completed":
print("\nOutput:", result.output)
# ── 5. Follow up ────────────────────────────────────────────────
updated = client.runs.append_message(
run.id, text="Now compare this with last year's trends."
)
final = client.runs.wait(updated.id, timeout=600)
print("\nUpdated:", final.output)
Error handling
from flymyai import AgentClient, FlyMyAIAgentError
client = AgentClient(api_key="fly-***")
try:
agent = client.agents.get("nonexistent-uuid")
except FlyMyAIAgentError as e:
print(e.status_code) # 404
print(e.response_body) # {"detail": "Not found."}
| Exception | When |
|---|---|
FlyMyAIAgentError | Any non-2xx API response (has .status_code and .response_body) |
TimeoutError | runs.wait() or runs.stream_events() exceeded timeout |
ValueError | Missing api_key at initialization |
Type reference
Agent
| Field | Type | Description |
|---|---|---|
uuid / id | str | Agent UUID |
name | str | Agent name |
user_prompt / goal | str | Instructions |
available_tools | list | Tool IDs (list view) or tool objects (detail view) |
status | AgentStatus | draft, initialization_required, active, archived |
all_tools_configured | bool | Whether all attached tools are configured |
generated_pipeline | dict | Auto-generated execution pipeline |
Run / RunDetail
| Field | Type | Description |
|---|---|---|
id | int | Execution ID |
status | ExecutionStatus | pending, running, completed, failed, cancelled |
agent_result / output | dict | Final output |
error | str | Error message (if failed) |
messages | list[dict] | Full conversation history |
logs | list[ExecutionLog] | Step-by-step logs (RunDetail only) |
is_terminal | bool | Whether the run has finished |
original_prompt | str | The prompt used for this run |
ExecutionLog
| Field | Type | Description |
|---|---|---|
id | int | Log entry ID |
type | str | declared_functions, tool_called, tool_call_exception, task_cancelled |
message | str | Human-readable description |
data | dict | Structured payload (arguments, results, etc.) |
Tool
| Field | Type | Description |
|---|---|---|
id | int | Tool ID |
mcp_tool / name | str | Tool identifier (e.g. "github", "tavily") |
is_configured | bool | All configuration steps complete |
is_active | bool | Tool enabled |
next_configuration_step | dict | Next step to complete (or None) |
user_config | dict | Current configuration values |
AvailableTool
| Field | Type | Description |
|---|---|---|
name | str | Tool identifier |
type | str | oauth, custom, composio, custom_class |
title | str | Human-readable name |
description | str | Short description |
categories | list[str] | Categories (e.g. ["Development"]) |
Compilation
| Field | Type | Description |
|---|---|---|
id | int | Compilation ID |
status | str | pending, compiling, compiled, running, completed, failed |
script_code | str | Generated Python script |
result | dict | Execution result |
error | str | Error message (if failed) |