Agent Service
agent-service is the heavy AI service. It runs the DeepAgents engine (a LangGraph loop over an OpenAI-compatible model via @langchain/openai) and streams results as Server-Sent Events (SSE). It also handles PDF parsing, translation, and realtime interview.
- Base URL (dev):
http://localhost:3112 - Global prefix:
/api - Swagger UI:
/api/docs
Sections
Runtime architecture
Internally agent-service is organized into flat modules:
runtime— the HTTP entry core (chat / agent / graph controllers) + run lifecycle, SSE writing, per-user daily token budget, trace persistence.engine— the DeepAgents engine (the single engine, a LangGraph loop over@langchain/openai); no upper abstraction — runtime / llm / workflows inject the concrete implementation directly.llm— assembles prompts → engine streaming, with circuit-breaking / retry (LLM resilience).workflows— analyze / research / rewrite workflows + multi-persona analysis.interview·translation·document— interview (incl. realtime WebSocket), translation, PDF.
How the engine and harness work (the LangGraph loop, virtual workspace, skills-as-tools, AgentRun→Step→Event persistence) is covered in Engine & harness.
Streaming model
Most agent endpoints respond with Content-Type: text/event-stream. The body is a sequence of frames separated by a blank line; each frame is a single data: line carrying one JSON event:
data: {"type":"run_started","runId":"clx..."}
data: {"type":"message_chunk","content":"Hello","runId":"clx...","stepId":"stp..."}
data: {"type":"done","runId":"clx..."}Every emitted event carries runId and stepId. The catalog of type values and the parsing rules are in SSE events.
Use curl -N (no buffering) to watch a stream, or a streaming HTTP client in code. Don’t await res.json() on these endpoints — they never return a single JSON body.
Runs, steps & events (the harness)
Every streamed run is persisted for observability and replay. A run is recorded as AgentRun → AgentStep → AgentEvent. You can fetch a past run after the fact:
| Action | Method & path |
|---|---|
| Get a run | GET /api/agent/runs/:runId |
| Get a run’s events | GET /api/agent/runs/:runId/events |
This means the runId you see in the stream is a durable handle — store it to later replay or audit what the agent did.
Endpoint map
| Capability | Endpoint | Shape |
|---|---|---|
| Chat | POST /api/chat | SSE |
| Agent run (generic task) | POST /api/agent/runs | SSE |
| Fetch run / events | GET /api/agent/runs/:runId[/events] | JSON |
| Research workflow | POST /api/graph/research | SSE |
| Analyze workflow | POST /api/graph/analyze (alias /api/graph/analyze-resume) | SSE |
| Rewrite workflow | POST /api/graph/rewrite | SSE |
| Multi-persona analysis | POST /api/graph/analyze-resume-multi | JSON |
| PDF parse | POST /api/pdf/parse | JSON |
| Translate | POST /api/translate/text | JSON |
| Translate (stream) | POST /api/translate/stream | SSE |
| Interview start / chat | POST /api/interview/start, POST /api/interview/chat | JSON |
| Interview delete session | DELETE /api/interview/session/:sessionId | JSON |
| Realtime interview | WS /api/interview/realtime/:sessionId | WebSocket |
| Health | GET /api/health | JSON |
Agent-service controllers are not Clerk-guarded at the controller level — they expect to sit behind the gateway. If you expose them publicly, enforce auth and rate limiting at your proxy.