Runs¶
A Run represents a single execution of an agent. It tracks the complete lifecycle from initiation to completion, including status, output, and any errors.
Run Lifecycle¶
stateDiagram-v2
[*] --> created
created --> in_progress
in_progress --> completed
in_progress --> failed
in_progress --> awaiting
in_progress --> cancelled
awaiting --> in_progress: resume
completed --> [*]
failed --> [*]
cancelled --> [*]
Run States¶
| Status | Description |
|---|---|
created |
Run has been created but not started |
in_progress |
Agent is currently executing |
completed |
Agent finished successfully |
failed |
Agent encountered an error |
awaiting |
Agent is waiting for additional input |
cancelled |
Run was cancelled by request |
Creating Runs¶
Synchronous¶
Execute and wait for completion:
run = client.run_sync(
agent: "echo",
input: [SimpleAcp::Models::Message.user("Hello")]
)
puts run.status # => "completed"
puts run.output.first # => Message object
Asynchronous¶
Start execution and poll for results:
run = client.run_async(
agent: "slow-processor",
input: [SimpleAcp::Models::Message.user("Process this")]
)
puts run.status # => "in_progress"
# Poll until complete
loop do
run = client.run_status(run.run_id)
break if run.terminal?
sleep 1
end
puts run.output
Streaming¶
Receive real-time events:
client.run_stream(
agent: "chat",
input: [SimpleAcp::Models::Message.user("Tell me a story")]
) do |event|
case event
when SimpleAcp::Models::RunStartedEvent
puts "Started: #{event.run_id}"
when SimpleAcp::Models::MessagePartEvent
print event.part.content
when SimpleAcp::Models::RunCompletedEvent
puts "\nDone!"
end
end
Run Properties¶
run = client.run_sync(agent: "echo", input: [...])
# Identification
run.run_id # => "550e8400-e29b-41d4-a716-446655440000"
run.agent_name # => "echo"
run.session_id # => "session-123" or nil
# Status
run.status # => "completed"
run.terminal? # => true
run.completed? # => true
run.failed? # => false
run.awaiting? # => false
run.cancelled? # => false
# Output
run.output # => Array of Messages
run.error # => Error object or nil
# Timestamps
run.created_at # => Time
run.finished_at # => Time or nil
Handling Different States¶
Completed Runs¶
run = client.run_sync(agent: "processor", input: [...])
if run.completed?
run.output.each do |message|
puts message.text_content
end
end
Failed Runs¶
run = client.run_sync(agent: "risky", input: [...])
if run.failed?
puts "Error code: #{run.error.code}"
puts "Error message: #{run.error.message}"
end
Awaiting Runs¶
run = client.run_sync(agent: "questioner", input: [...])
if run.awaiting?
# The agent is waiting for more input
puts run.await_request.message.text_content
# Resume with a response
run = client.run_resume_sync(
run_id: run.run_id,
await_resume: SimpleAcp::Models::MessageAwaitResume.new(
message: SimpleAcp::Models::Message.user("My response")
)
)
end
Run Management¶
Get Run Status¶
Get Run Events¶
events = client.run_events("run-id-here")
events.each do |event|
puts "#{event.type}: #{event.inspect}"
end
Cancel a Run¶
Server-Side Runs¶
On the server, runs are managed internally:
# Create and execute a run programmatically
run = server.run_sync(
agent_name: "processor",
input: [SimpleAcp::Models::Message.user("Data")],
session_id: "optional-session"
)
# Stream execution
server.run_stream(
agent_name: "streamer",
input: messages
) do |event|
# Handle events
end
Run with Sessions¶
Associate runs with sessions for stateful interactions:
# Client side
client.use_session("conversation-123")
# All runs now use this session
run1 = client.run_sync(agent: "chat", input: [...])
run2 = client.run_sync(agent: "chat", input: [...])
# Server side
run = server.run_sync(
agent_name: "chat",
input: messages,
session_id: "conversation-123"
)
Best Practices¶
Always Check Status¶
run = client.run_sync(agent: "...", input: [...])
case run.status
when "completed"
process_output(run.output)
when "failed"
handle_error(run.error)
when "awaiting"
handle_await(run)
else
log_unexpected_status(run.status)
end
Use Streaming for Long Operations¶
# Better UX for slow operations
client.run_stream(agent: "slow-agent", input: [...]) do |event|
show_progress(event)
end
Handle Timeouts¶
run = client.run_async(agent: "slow", input: [...])
timeout = Time.now + 60
loop do
run = client.run_status(run.run_id)
break if run.terminal?
if Time.now > timeout
client.run_cancel(run.run_id)
raise "Run timed out"
end
sleep 1
end
Next Steps¶
- Learn about Sessions for stateful runs
- Explore Events for real-time updates
- See Client Streaming for advanced streaming patterns