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

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

Aperta
#952 0 commenti 17 reazioni 0 assegnatari Vedi su GitHub
enhancement Integration
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.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.