Conversation with async
A ready-to-run example is available here.
Concurrent agents
Run multiple agent tasks in parallel using asyncio.gather():
async def main():
loop = asyncio.get_running_loop()
callback = AsyncCallbackWrapper(callback_coro, loop)
# Create multiple conversation tasks running in parallel
tasks = [
loop.run_in_executor(None, run_conversation, callback),
loop.run_in_executor(None, run_conversation, callback),
loop.run_in_executor(None, run_conversation, callback)
]
results = await asyncio.gather(*tasks)
Ready-to-run example
This example demonstrates usage of a Conversation in an async context (e.g.: From a fastapi server). The conversation is run in a background thread and a callback with results is executed in the main runloop
"""
This example demonstrates usage of a Conversation in an async context
(e.g.: From a fastapi server). The conversation is run in a background
thread and a callback with results is executed in the main runloop
"""
import asyncio
import os
from pydantic import SecretStr
from faheemcode.sdk import (
LLM,
Agent,
Conversation,
Event,
LLMConvertibleEvent,
get_logger,
)
from faheemcode.sdk.conversation.types import ConversationCallbackType
from faheemcode.sdk.tool import Tool
from faheemcode.sdk.utils.async_utils import AsyncCallbackWrapper
from faheemcode.tools.file_editor import FileEditorTool
from faheemcode.tools.task_tracker import TaskTrackerTool
from faheemcode.tools.terminal import TerminalTool
logger = get_logger(__name__)
# Configure LLM
api_key = os.getenv("LLM_API_KEY")
assert api_key is not None, "LLM_API_KEY environment variable is not set."
model = os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929")
base_url = os.getenv("LLM_BASE_URL")
llm = LLM(
usage_id="agent",
model=model,
base_url=base_url,
api_key=SecretStr(api_key),
)
# Tools
cwd = os.getcwd()
tools = [
Tool(
name=TerminalTool.name,
),
Tool(name=FileEditorTool.name),
Tool(name=TaskTrackerTool.name),
]
# Agent
agent = Agent(llm=llm, tools=tools)
llm_messages = [] # collect raw LLM messages
# Callback coroutine
async def callback_coro(event: Event):
if isinstance(event, LLMConvertibleEvent):
llm_messages.append(event.to_llm_message())
# Synchronous run conversation
def run_conversation(callback: ConversationCallbackType):
conversation = Conversation(agent=agent, callbacks=[callback])
conversation.send_message(
"Hello! Can you create a new Python file named hello.py that prints "
"'Hello, World!'? Use task tracker to plan your steps."
)
conversation.run()
conversation.send_message("Great! Now delete that file.")
conversation.run()
async def main():
loop = asyncio.get_running_loop()
# Create the callback
callback = AsyncCallbackWrapper(callback_coro, loop)
# Run the conversation in a background thread and wait for it to finish...
await loop.run_in_executor(None, run_conversation, callback)
print("=" * 100)
print("Conversation finished. Got the following LLM messages:")
for i, message in enumerate(llm_messages):
print(f"Message {i}: {str(message)[:200]}")
# Report cost
cost = llm.metrics.accumulated_cost
print(f"EXAMPLE_COST: {cost}")
if __name__ == "__main__":
asyncio.run(main())
You can run the example code as-is.
Bring your own provider key
export LLM_API_KEY="your-api-key"
export LLM_MODEL="anthropic/claude-sonnet-4-5-20250929" # or openai/gpt-4o, etc.
cd software-agent-sdk
uv run python examples/01_standalone_sdk/11_async.py
Faheem Code Cloud key
# https://app.faheemcode.ai/settings/api-keys
export LLM_API_KEY="example-user-api-key"
export LLM_MODEL="faheemcode/claude-sonnet-4-5-20250929"
cd software-agent-sdk
uv run python examples/01_standalone_sdk/11_async.py
Next steps
- Persistence - Save and restore conversation state
- Send Message While Processing - Interrupt running agents