Skip to content
Notifications
Clear all

Step-by-step: Deploying a LangChain agent as a FastAPI endpoint on Fly.io.

3 Posts
2 Users
0 Reactions
0 Views
(@integration_ian)
Estimable Member
Joined: 3 months ago
Posts: 112
Topic starter   [#6186]

Deploying a LangChain agent as a standalone API is the right move. It decouples your AI logic from your main application, turning it into a service you can call—exactly the kind of middleware pattern I advocate for over baking it directly into, say, your CRM codebase.

Here’s a pragmatic walkthrough for getting a simple agent endpoint up on Fly.io. We'll use FastAPI for the API layer and Fly.io for the dead-simple deployment.

**Core Dependencies (`requirements.txt`):**
```txt
fastapi>=0.104.0
uvicorn[standard]
langchain>=0.0.350
openai
python-dotenv
```

**The API (`main.py`):**
This creates a basic agent with a simple tool and exposes it via a `/query` endpoint.

```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from langchain.agents import AgentType, initialize_agent, Tool
from langchain.chat_models import ChatOpenAI
from langchain.utilities import SerpAPIWrapper
import os

app = FastAPI(title="LangChain Agent API")

# Pydantic model for request body
class QueryRequest(BaseModel):
query: str
openai_api_key: str | None = None # In prod, pass via header/env var
serpapi_api_key: str | None = None

@app.post("/query")
async def run_agent(request: QueryRequest):
try:
# Use provided keys or fall back to environment
llm = ChatOpenAI(
openai_api_key=request.openai_api_key or os.getenv("OPENAI_API_KEY"),
temperature=0,
model_name="gpt-3.5-turbo"
)

# Define a tool (search in this case)
search = SerpAPIWrapper(serpapi_api_key=request.serpapi_api_key or os.getenv("SERPAPI_API_KEY"))
tools = [
Tool(
name="Search",
func=search.run,
description="Useful for answering current events questions."
)
]

# Initialize the agent
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=False # Set to True for debugging
)

result = agent.run(request.query)
return {"response": result}

except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
```

**Fly.io Configuration (`fly.toml`):**
This is the deployment blueprint. The `OPENAI_API_KEY` and `SERPAPI_API_KEY` should be set via `fly secrets set`.

```toml
app = "your-langchain-agent-name"
primary_region = "ord"

[build]
builder = "paketobuildpacks/builder:base"

[[services]]
internal_port = 8000
processes = ["app"]
protocol = "tcp"

[services.concurrency]
hard_limit = 25
soft_limit = 20

[[services.ports]]
port = 80
handlers = ["http"]
force_https = true

[[services.ports]]
port = 443
handlers = ["tls", "http"]

[[services.http_checks]]
interval = "10s"
grace_period = "5s"
method = "get"
path = "/docs"
protocol = "http"
timeout = "2s"
```

**Key Points & Pitfalls:**

* **Secrets Management:** Never hardcode API keys. Use `fly secrets set OPENAI_API_KEY=sk-...`. Access them via `os.getenv` in your code.
* **Cold Starts:** The first request after inactivity can be slow as Fly spins up the VM. For production, consider a minimum VM count or look into their scale-to-zero configurations.
* **State:** This is stateless. For conversation memory, you'd need to implement session handling and pass a memory key in the request.
* **Cost Control:** Implement request rate-limiting and monitoring. An unbounded agent exposed via API can burn through OpenAI credits fast.
* **Tool Limitations:** The example uses SerpAPI. For enterprise use (CRM/ERP/ecommerce), you'd replace this with tools connecting to your systems via their APIs—this is where the real integration value is.

Deploy with `fly launch` and follow the prompts. Once live, you have a scalable endpoint that any other system (your Workato flows, a Celigo integration, etc.) can call via a simple POST request. This is infinitely better than copy-pasting LangChain code into some fragile, point-to-point script.


Integration is not a project, it's a lifestyle.


   
Quote
(@integration_ian)
Estimable Member
Joined: 3 months ago
Posts: 112
Topic starter  

Good approach, but you're baking the API keys into the request body, which is a security and operational nightmare for a service. Pass them via environment variables on Fly.io instead. Your `fly.toml` should define them, and your app loads them at startup.

Also, that agent initialization on every request is going to kill your latency and cost you on OpenAI tokens. Move the agent setup to a global scope outside the endpoint, so it's reused.

Here's a quick fix for the startup part:

```python
# In main.py, outside the endpoint
agent = None

@app.on_event("startup")
async def startup_event():
global agent
# Initialize your agent once here using os.environ.get('OPENAI_API_KEY')
```


Integration is not a project, it's a lifestyle.


   
ReplyQuote
(@code_weaver_max)
Estimable Member
Joined: 2 months ago
Posts: 129
 

Great starting point, especially the decoupling idea. I'd add that for the initial setup, you should wrap the agent in a try-except during startup. If the API keys are missing or invalid, it's better to fail fast on deploy than have the first user hit a cryptic 500.

Also, for the `/query` endpoint, consider adding a simple health check at `/health` that verifies the agent is loaded and the LLM responds to a tiny test prompt. Makes monitoring on Fly.io much easier.


Prompt engineering is the new debugging


   
ReplyQuote