A frame to help you reason through the assignment — concepts, diagrams, and the API map. It deliberately does not contain the answers or filled-in activity code. Instead it gives you the questions to ask yourself and the method to get there. The work — and the learning — is in packaging the agent, inspecting a Studio/LangSmith trace, shipping it, and writing your own conclusions.
Source repo:
09_Agent_Servers/(a packaged LangGraph agent + a Next.jsfrontend/). No notebook — Q1/Q2 are answered inREADME.md. Corpus:data/cat_health_guidelines.pdf(a feline-health PDF the RAG tool indexes in-memory; benign).
| You want to… | Reach for | One-liner |
|---|---|---|
| Tell LangGraph what graphs exist | langgraph.json graphs |
"simple_agent": "app.graphs.simple_agent:graph" (id → module:attribute) |
| Export a runnable graph | a module-level graph |
graph = create_agent(model=..., tools=..., system_prompt=...) |
| Run the agent API locally | langgraph dev |
serves http://localhost:2024 + opens LangGraph Studio |
| Self-host a prod container | langgraph up |
local Docker; you own scaling/uptime/auth |
| Deploy to LangSmith cloud | langgraph deploy |
managed build+host (needs LangSmith Plus) → Deployment URL |
| Talk to the agent in Python | langgraph_sdk.get_client |
client.runs.stream(None, "agent", input={...}, stream_mode="updates") |
| Stream the agent into a UI | @langchain/react useStream |
useStream({ apiUrl: "/api", assistantId: "simple_agent" }) |
| Hide the API key from the browser | langgraph-nextjs-api-passthrough |
initApiPassthrough({ apiUrl, apiKey, runtime: "edge" }) in route.ts |
| Mark a var public in Next.js | NEXT_PUBLIC_ prefix |
only NEXT_PUBLIC_* reaches the browser; everything else is server-only |
| Deploy the UI | vercel / vercel --prod |
set LANGGRAPH_API_URL, LANGSMITH_API_KEY, NEXT_PUBLIC_API_URL |
| See what the agent actually did | LangSmith traces / Studio | every run is traced; Studio steps through nodes + tool calls |
Anchor: LangSmith hosts the agent as an API; Vercel hosts the UI and the
server-side proxy that injects the secret — the browser only ever talks to
same-origin /api/*.
flowchart LR
User[User in browser] --> Vercel[Next.js UI on Vercel]
Vercel -->|"/api/* passthrough (injects key server-side)"| LS[LangSmith Agent API]
LS --> Agent[Your LangGraph graph]
Agent --> Tools[Tavily + Arxiv + RAG tool]
LS --> Traces[LangSmith tracing]
subgraph local[Local dev]
Dev["langgraph dev :2024"] --> Studio[LangGraph Studio]
end
ASCII fallback:
browser ─► Vercel UI ─► /api proxy (adds LANGSMITH_API_KEY server-side) ─► LangSmith Agent API ─► graph ─► tools
└─► LangSmith traces
local: langgraph dev :2024 ─► LangGraph Studio (debug/step/fork)
Why this shape? A deployed agent is a stateful API (threads / runs / assistants + streaming), not a website. The two deployment targets map to two concerns: LangSmith runs + observes the agent; Vercel serves the UI and keeps the secret on the trusted server tier. The same compiled graph runs in Studio (debug) and in production (hosted) — only the environment differs.
uv sync # agent deps (Python 3.13)
cp .env.example .env # fill OPENAI_API_KEY, TAVILY_API_KEY, LANGSMITH_API_KEY
cd frontend && npm install # the frontend ships complete — no create-next-app needed| Component | Role |
|---|---|
app/models.py |
model factory get_chat_model() (default gpt-5.4-mini, temperature=0) |
app/tools.py |
tool belt: TavilySearch, ArxivQueryRun, retrieve_information (RAG) |
app/rag.py |
loads data/*.pdf → split 750/0 → text-embedding-3-small → in-memory Qdrant |
app/graphs/simple_agent.py |
create_agent(...) → exports compiled graph |
langgraph.json |
manifest: graphs + assistants the server exposes |
frontend/app/api/[...path]/route.ts |
secure passthrough — injects the key server-side |
frontend/components/chat.tsx |
useStream chat UI pointed at /api |
A notebook agent becomes a server by exporting a compiled graph and
registering it. langgraph.json maps a graph_id to "module:attribute" and
declares named assistants. dependencies: ["."] installs the local package;
env: ".env" loads keys. Docs: https://docs.langchain.com/langgraph-platform/
"graphs": { "simple_agent": "app.graphs.simple_agent:graph" }langgraph dev serves the Agent Server API at :2024 with hot reload and opens
Studio. Studio = debugging: visualize topology, step through runs, inspect
tool calls, fork threads, switch assistants. Not a production UI. Docs:
https://docs.langchain.com/langgraph-platform/langgraph-studio
The production integration path. A passing local smoke test proves the manifest, graph import, and streaming all work — the README gate before deploying.
from langgraph_sdk import get_client
client = get_client(url="http://localhost:2024")
for chunk in client.runs.stream(None, "agent", input={"messages": [...]}, stream_mode="updates"):
...langgraph deploy = managed LangSmith cloud build+host (needs Plus) → a
https://<...>.us.langgraph.app Deployment URL + optional auto-update-on-push.
langgraph up = self-hosted Docker container. Either way you get the same API
surface (threads/runs/assistants) plus tracing. Docs:
https://docs.langchain.com/langsmith/deployments.
Docker/self-host instructions: langgraph up (Docker required, production-like local) —
https://docs.langchain.com/langsmith/local-dev-testing#langgraph-up; standalone Agent
Servers via Docker / Docker Compose / Kubernetes —
https://docs.langchain.com/langsmith/deploy-standalone-server.
Cloud deploy (langgraph deploy or GitHub→UI) requires Plus — $39/seat/mo 1.
Free without Plus: everything local (langgraph dev + Studio + SDK, all of Part 1),
tracing (5k traces/mo on the Developer plan), and self-hosting via langgraph up (Docker).
Check your plan: LangSmith → Settings → Billing and Usage
(smith.langchain.com/settings/payments) — a personal org is Developer (free, no cloud
deploy); a team/shared org is Plus. An "Upgrade to Plus" banner means you're not on it.
Upgrade is self-serve there (add a card); Enterprise is contact-sales. Plus includes
1 free Dev deployment, unlimited runs — enough for this assignment; beyond it, ~$0.005/run
plus uptime (langgraph up, or record the Loom against the local Studio
demo (the README accepts "Studio debugging" as one of its two demo options). Cost table:
pricing 2.
| Plan | Price | Free traces/mo | Cloud deploy? |
|---|---|---|---|
| Developer | $0/seat, 1 seat | 5,000 | ❌ |
| Plus | $39/seat/mo | 10,000 | ✅ 1 free Dev deployment |
| Enterprise | custom | custom | ✅ + self-hosted/hybrid |
create_agent wires a ReAct-style agent: the model decides when to call a tool,
the tool runs, control returns until the model gives a final answer. Tools: Tavily
(web), Arxiv (papers), retrieve_information (RAG over the cat-health PDF).
A "use client" component subscribes to the agent's event stream and renders
messages as they arrive. Point it at the same-origin /api proxy, not the
LangSmith URL directly. Docs: https://www.npmjs.com/package/@langchain/react
const { messages, submit, isLoading } = useStream({ apiUrl: "/api", assistantId: "simple_agent" });Anything in client code is readable by the user. The passthrough route runs
server-side and injects LANGSMITH_API_KEY into the upstream request; the
browser only sees /api/*. Only NEXT_PUBLIC_* vars are public. Docs:
https://www.npmjs.com/package/langgraph-nextjs-api-passthrough
export const { GET, POST, ... } = initApiPassthrough({
apiUrl: process.env.LANGGRAPH_API_URL, apiKey: process.env.LANGSMITH_API_KEY, runtime: "edge" });Set Root Directory to frontend, add LANGGRAPH_API_URL + LANGSMITH_API_KEY
(server-only) + NEXT_PUBLIC_API_URL, then vercel --prod. Verify end-to-end:
the live site streams, tool calls fire, traces appear in LangSmith. Docs:
https://vercel.com/docs/frameworks/nextjs
Q1 — Why does LangSmith deploy your agent as an API backend only, and why still a separate Vercel frontend?
Method to get there — ask yourself:
- When you hit your deployed agent, what comes back — HTML you could render in a browser, or JSON/streamed events? What does that tell you about whether LangSmith can be your website?
- List what the agent API exposes (threads? runs? assistants?). Is any of that a user interface?
- If you skipped Vercel and pointed the browser directly at the LangSmith URL, what would the user need in the request — and what does §7 say about putting that in the browser?
- Frame your answer as "two concerns, two hosts." Name each host's job in one line.
Method to get there — ask yourself:
- Open devtools on any site → Network + Sources. What can you read? Could a secret compiled into client JS stay hidden?
- In Next.js, which env vars reach the browser? What does the
NEXT_PUBLIC_prefix do, and why areLANGGRAPH_API_URL/LANGSMITH_API_KEYdeliberately not prefixed whileNEXT_PUBLIC_API_URLis? - Trace one request: browser →
/api/*→ ? Where doesinitApiPassthroughadd the key — on the user's machine or on Vercel's server? - What could someone do with your key if they lifted it from the bundle? Let that consequence anchor your "why."
Deliverable: a new graph that, after the agent answers, has a judge model
decide whether the response was helpful and loops back for another attempt if not —
with a safe loop limit — registered in langgraph.json, deployed, with traces
compared for a passing vs failing query.
Method to get there — ask yourself:
- The provided agent uses
create_agent. Can you insert a step that runs after the final answer with it? If not, what lower-level construct lets you own the nodes and edges (and a cycle)? - What nodes do you need — who answers, who runs tools, who judges? Draw the edges: when does the judge send control back to the agent vs to the end?
- How will the judge "decide"? What does it compare (the answer against…?), and how do you keep its output easy to branch on?
- What would happen if the judge kept saying "not helpful"? Design the loop limit first — what will you count, and where do you force the end?
- In Studio/LangSmith, inspect both runs: does the passing query end in one pass? Does the failing one show the retry edge firing? Where do you see the judge call?
- Reflect (the README asks): is the loop's logic any different in Studio vs production — or is it the same graph in a different environment?
Deliverable: describe (optionally implement) how to add authentication so each user only sees their own threads. Method to get there — ask yourself:
- Hiding the chat page behind a login in React — does that actually stop someone from reading another user's threads through the API? Where must the real check live?
- What would the server need to know on each request to scope threads to one user, and what could you stamp on a thread when it's created so reads can be filtered?
- Where should the user's token be attached — the same place §7 puts the API key, or the browser? Why?
- Look at the README's
lsd-custom-route-react-uireference for the pattern.
Grounded against the LangChain docs and the LangChain pricing page (verify — plans and prices change; figures current ~mid-2026).
LangSmith Plus / deployment / cost (§4½):
- Billing setup, plan check, and upgrade-to-Plus steps — https://docs.langchain.com/langsmith/billing
- Deployment environments (Cloud vs standalone vs self-hosted; plan requirements) — https://docs.langchain.com/langsmith/deployment
- Local development & testing (
langgraph devvslanggraph up) — https://docs.langchain.com/langsmith/local-dev-testing
Docker / self-host deployment (langgraph up, standalone container):
- Self-host standalone Agent Servers — Docker, Docker Compose, Kubernetes — https://docs.langchain.com/langsmith/deploy-standalone-server
langgraph up(Docker required; production-like local: API + PostgreSQL + Redis on :8123) — https://docs.langchain.com/langsmith/local-dev-testing#langgraph-up- LangGraph CLI
up/build/dockerfilecommands — https://docs.langchain.com/langsmith/cli - Self-hosted deployment topologies (standalone vs hybrid vs full platform) — https://docs.langchain.com/langsmith/deploy-to-self-hosted-overview
Packaging, server, SDK, frontend:
- LangGraph CLI reference (
dev/build/deploy/up) — https://docs.langchain.com/langsmith/cli - Application structure (
langgraph.json) — https://docs.langchain.com/langsmith/application-structure - Default assistants (the run id is the graph id) — https://docs.langchain.com/langsmith/assistants
- Run a local server / Studio — https://docs.langchain.com/oss/python/langgraph/local-server
useStream(frontend streaming) — https://www.npmjs.com/package/@langchain/react- Secure passthrough proxy — https://www.npmjs.com/package/langgraph-nextjs-api-passthrough
- Deploy the UI on Vercel (Next.js) — https://vercel.com/docs/frameworks/nextjs
Footnotes
-
Deploy to Cloud — "Agent deployments running on Cloud require a Plus plan or above" — https://docs.langchain.com/langsmith/deploy-to-cloud-overview ↩
-
LangSmith pricing (Developer $0 / Plus $39-seat / Enterprise custom; free-trace tiers; deployment run + uptime rates) — https://www.langchain.com/pricing ↩