Skip to main content

Runs

A Run is a single execution of an agent. You start a run, the agent works autonomously using its configured goal and tools, and you get output when it finishes. Every run is logged with a full event timeline for debugging and observability.

Run Lifecycle

StatusDescription
pendingQueued, waiting to start
runningAgent is actively executing -- planning, calling tools, reasoning
completedFinished successfully, output available
failedSomething went wrong -- error string available
cancelledCancelled by the user before completion

Starting a Run

A run is started by specifying the agent ID. The agent uses the goal configured at creation time.

from flymyai import AgentClient

client = AgentClient(api_key="fly-***")

run = client.runs.create(agent_id="agent_abc123")

Run Events

Every run emits ExecutionLog events that provide full visibility into what the agent is doing. Each event has .type, .message, .data, and .created_at.

Event TypeDescription
declared_functionsAgent declared the functions it plans to use
tool_calledAgent invoked a tool
tool_call_exceptionA tool call failed with an error
task_cancelledThe run was cancelled

Streaming Events

client.runs.stream_events(run_id) yields ExecutionLog objects using polling-based delivery (not SSE).

for event in client.runs.stream_events(run.id):
if event.type == "declared_functions":
print(f"Functions: {event.data}")
elif event.type == "tool_called":
print(f"Tool called: {event.message}")
print(f"Details: {event.data}")
elif event.type == "tool_call_exception":
print(f"Tool error: {event.message}")
elif event.type == "task_cancelled":
print("Run was cancelled")

Example event stream:

[declared_functions]     Declared: tavily_search, browser_navigate
[tool_called] Called tavily_search with query "renewable energy trends 2026"
[tool_called] Called browser_navigate to extract page content
[tool_called] Called tavily_search with query "solar cost decline statistics"

Getting Results

A completed run provides .status, .output, .error, .logs, .messages, and .original_prompt.

# Wait synchronously (polls until terminal status)
result = client.runs.wait(run.id, timeout=300, poll_interval=2.0)

print(f"Status: {result.status}")
print(f"Output: {result.output}")

# Or fetch the current state without waiting
result = client.runs.get(run.id)

Run Detail Fields

FieldDescription
statusCurrent run status (see lifecycle above)
outputThe agent's result (alias for agent_result)
errorError message string (when status is failed)
logsList of ExecutionLog entries
messagesConversation messages from the run
original_promptThe prompt that was sent to the agent

Follow-up Messages

You can append a follow-up message to a run:

client.runs.append_message(run.id, text="Can you also check competitor pricing?")

Cancelling a Run

Cancel a run that is still in progress:

client.runs.cancel(run.id)

Listing Runs

# All runs for an agent
runs = client.runs.list(agent_id="agent_abc123")

for run in runs:
print(f"{run.id}: {run.status} ({run.created_at})")

Error Handling

When a run fails, run.error contains a plain error string describing what went wrong.

result = client.runs.get(run.id)

if result.status == "failed":
print(f"Error: {result.error}")
tip

Use stream_events() alongside wait() to get real-time visibility into what the agent is doing. Events of type tool_call_exception can help you diagnose tool-related failures before the run finishes.

Freeze & Re-run

Once a run does what you wanted, you can freeze it. The backend reads the chat, the agent's input_description / output_description, and the schemas, then distills the canonical input → output pipeline into a Markdown instruction. Future executions skip exploration and follow that frozen plan.

# Step 1 - freeze the run (returns once status is "compiled")
compilation = client.agents.compile_from_run(run.id, timeout=120)
print(compilation.instruction_md)

# Step 2a - re-run without variables (agent has no input_schema)
result = client.compilations.run_instruction_and_wait(compilation.id)

# Step 2b - re-run with fresh variables (agent has an input_schema)
result = client.compilations.run_instruction_and_wait(
compilation.id,
variables={"website_url": "https://example.com"},
)

print(result.output) # shaped by output_schema
print(result.output["score"]) # individual fields

What gets dropped: any chat turn outside the input → output path defined by your descriptions and schemas. Exploratory questions, one-off favors, abandoned branches — none of them survive the freeze. See the Python SDK reference for the lower-level building blocks (freeze, run_instruction, wait).

Next Steps

  • Tools -- browse the catalog, configure, and attach tools
  • Agents -- configure the agent that runs execute