ag-ui-protocol / ag-ui-protocol/ag-ui
[Feature] Add support for local/in-process LangGraph graphs (TypeScript)
- Lingua principale
- Python
- Stelle
- 15.9k
- Fork
- 1.4k
- Merge medio
- 1g 17h
- PR unite (30g)
- 163
Descrizione
# Feature Request: Add support for local/in-process LangGraph graphs
## Summary
Add a `LangGraphLocalAgent` class that works with compiled LangGraph graphs directly in-process, without requiring a LangGraph Platform deployment.
## Motivation
The current `LangGraphAgent` requires a LangGraph Platform server (`deploymentUrl` + `langsmithApiKey`). However, many developers want to:
1. **Run locally during development** - No cloud setup needed
2. **Self-host without Platform** - Deploy their own backend with embedded graphs
3. **Reduce latency** - Skip HTTP round-trips for in-process execution
4. **Simplify architecture** - Single process for simpler apps
The Python `ag-ui-langgraph` package already supports both modes. This would bring parity to the TypeScript SDK.
## Proposed Solution
Add a new `LangGraphLocalAgent` class alongside the existing `LangGraphAgent`:
```typescript
import { StateGraph, MessagesAnnotation } from "@langchain/langgraph";
import { LangGraphLocalAgent } from "@ag-ui/langgraph";
// Compile your graph locally
const graph = new StateGraph(MessagesAnnotation)
.addNode("chat", async (state) => { /* ... */ })
.compile();
// Use directly with AG-UI - no server needed
const agent = new LangGraphLocalAgent({
graph,
agentId: "my-agent",
});
```
## Implementation Approach
### Architecture
```
src/
├── index.ts # exports both agents
├── agent.ts # LangGraphAgent (platform) - unchanged
├── local-agent.ts # LangGraphLocalAgent (NEW)
├── types.ts # shared types (extend existing)
├── event-handler.ts # shared event transformation (NEW)
└── message-converter.ts # AG-UI ↔ LangChain messages (NEW)
```
### Key Differences
| Aspect | LangGraphAgent | LangGraphLocalAgent |
|--------|---------------|---------------------|
| Input | `deploymentUrl` | `graph` instance |
| Connection | HTTP via LangGraphClient | Direct `graph.streamEvents()` |
| Events | Platform format | Raw LangGraph events |
### Shared Code
Both agents would share:
- `types.ts` - `MessageInProgress`, `ThinkingProcess`, `CustomEventNames`, etc.
- Event emission logic for AG-UI events
- State filtering (`SchemaKeys` / `stateSchema`)
- Message conversion utilities
### Event Transformation
The local agent processes raw LangGraph `streamEvents()`:
```typescript
// Raw LangGraph events
"on_chat_model_stream" → TEXT_MESSAGE_CONTENT / TOOL_CALL_ARGS
"on_chat_model_end" → TEXT_MESSAGE_END / TOOL_CALL_END
"on_tool_end" → TOOL_CALL_RESULT
"on_chain_start/end" → STEP_STARTED / STEP_FINISHED
"on_custom_event" → CUSTOM / manually_emit_* handling
```
## Features Included
I have a working implementation with full feature parity to the Python adapter:
- [x] **Core streaming** - Text messages, tool calls
- [x] **hasFunctionStreaming** - Prevents duplicate tool call events
- [x] **Extended Thinking** - Claude/OpenAI o1 reasoning blocks
- [x] **Interrupt handling** - Human-in-the-loop workflows
- [x] **Custom events** - `manually_emit_message`, `manually_emit_state`, `exit`
- [x] **State schema filtering** - Control which keys are sent to client
- [x] **PredictStateTool** - Optimistic UI updates
- [x] **Time-travel** - `regenerateFromMessage()` with checkpoints
- [x] **Multimodal** - Image content (base64/URL)
- [x] **Message conversion** - AG-UI ↔ LangChain formats
## Example Usage
### Basic
```typescript
import { LangGraphLocalAgent } from "@ag-ui/langgraph";
const agent = new LangGraphLocalAgent({
graph: compiledGraph,
agentId: "assistant",
});
// Use with CopilotKit
const runtime = new CopilotRuntime({ agents: [agent] });
```
### With Express
```typescript
import { addLangGraphEndpoint } from "@ag-ui/langgraph";
import express from "express";
const app = express();
addLangGraphEndpoint(app, graph, "/api/agent");
```
### With Next.js App Router
```typescript
// app/api/agent/route.ts
import { createNextHandler } from "@ag-ui/langgraph";
export const POST = createNextHandler({ graph });
```
### Advanced Configuration
```typescript
const agent = new LangGraphLocalAgent({
graph,
agentId: "my-agent",
// State filtering - only send these keys to client
stateSchema: ["messages", "userPreferences"],
// Predictive state for optimistic UI
predictStateTool: {
enabled: true,
stateSchema: {
documentContent: { type: "string" },
selectedColor: { type: "string" }
}
},
// Debug mode
debug: true,
});
```
## Questions for Maintainers
1. **Naming**: `LangGraphLocalAgent` vs `LangGraphInProcessAgent` vs other?
2. **Package structure**: Same package or separate `@ag-ui/langgraph-local`?
3. **Shared code**: How much refactoring of existing `agent.ts` is acceptable?
## Related
- Python `ag-ui-langgraph` already supports local graphs
- Issue #83 - Original request for LangGraph integration
- Issue #175 - Question about using without LangGraph API
## I Can Contribute
I have a complete working implementation and would be happy to submit a PR once we align on the approach. The code is TypeScript, fully typed, and follows the patterns established in the existing codebase.
---
**Environment:**
- `@langchain/langgraph`: 0.2.x and 1.x compatible
- `@ag-ui/client`: 0.0.42+
- Node.js / Bun / Deno (Fetch API compatible)
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.