Documentation Index
Fetch the complete documentation index at: https://docs.upsonic.ai/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks you through:
- Building a minimal FastAPI app with a Upsonic agent using async endpoints and
agent.do_async()
- Containerizing with Docker
- Running locally
Why async with FastAPI
FastAPI is async-native. Use agent.do_async() in your route handlers so the event loop is not blocked during LLM and tool calls. That keeps the server responsive under concurrent requests.
Setup
Create a new directory for your project
Create a new directory and navigate into it:mkdir my-upsonic-project
cd my-upsonic-project
Resulting structure:my-upsonic-project/
├── main.py
├── Dockerfile
├── .dockerignore
├── pyproject.toml
Initialize the project with uv
uv init
uv add fastapi upsonic uvicorn anthropic
Step 1: Create the FastAPI app
Create `main.py` with async endpoints and `agent.do_async()`
from fastapi import FastAPI
from upsonic import Agent, Task
from upsonic.tools import WebSearch
app = FastAPI()
agent = Agent(
"anthropic/claude-sonnet-4-6",
name="Customer Support",
company_url="https://your-company.com",
company_objective="To provide excellent customer service and support",
)
@app.get("/ask")
async def ask(query: str) -> dict[str, str]:
task = Task(query, tools=[WebSearch])
response = await agent.do_async(task)
return {"response": response}
Set ANTHROPIC_API_KEY
export ANTHROPIC_API_KEY=your_api_key # On Windows: set ANTHROPIC_API_KEY=your_api_key
Run the app
uv run uvicorn main:app --reload
Step 2: Docker
Create a `.dockerignore` file
Create a `Dockerfile`
FROM python:3.12-slim
WORKDIR /app
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY . .
CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Build and run the image
docker build -t my-upsonic-app .
docker run -p 8000:8000 -e ANTHROPIC_API_KEY=your_api_key my-upsonic-app
Access the app
Open http://localhost:8000. Interactive API docs: http://localhost:8000/docs.
Step 3: Structured responses (async)
Use Pydantic models and agent.do_async() with response_format for typed JSON responses.
Add structured response in `main.py`
from fastapi import FastAPI
from upsonic import Agent, Task
from upsonic.tools import WebSearch
from pydantic import BaseModel
from typing import List
app = FastAPI()
class TravelRecommendation(BaseModel):
destination: str
attractions: List[str]
best_time_to_visit: str
estimated_budget: str
agent = Agent(
"anthropic/claude-sonnet-4-6",
name="Travel Advisor",
company_url="https://your-travel-company.com",
company_objective="To provide personalized travel recommendations and advice",
)
@app.get("/travel-recommendation")
async def get_travel_recommendation(
destination_type: str, budget: str, duration: str
) -> TravelRecommendation:
task = Task(
f"Recommend a travel destination for a {duration} trip with {destination_type} experience and {budget} budget",
tools=[WebSearch],
response_format=TravelRecommendation,
)
response = await agent.do_async(task)
return response
@app.get("/ask")
async def ask(query: str) -> dict[str, str]:
task = Task(query, tools=[WebSearch])
response = await agent.do_async(task)
return {"response": response}
Test the structured endpoint
curl "http://localhost:8000/travel-recommendation?destination_type=beach&budget=medium&duration=7%20days"
Key takeaways
- Use async route handlers and
await agent.do_async(task) so FastAPI’s event loop stays non-blocking.
- Use
response_format=YourPydanticModel when you need structured JSON.
- Run in production with
uv run uvicorn main:app --host 0.0.0.0 --port 8000 or via Docker as above.