ag-ui-protocol / ag-ui-protocol/ag-ui

[Feature] Add support for local/in-process LangGraph graphs (TypeScript)

Abierto
#952 0 comentarios 17 reacciones 0 asignados Ver en GitHub
enhancement Integration
Lenguaje dominante
Python
Estrellas
15.9k
Forks
1.4k
Merge medio
1 d 17 h
PR fusionados (30 d)
163

Descripción

# 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)

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.