### Clone Repository and Install Dependencies
Source: https://github.com/langchain-ai/agent-inbox/blob/main/README.md
Clone the Agent Inbox repository and install its dependencies using yarn. Ensure Node.js and yarn are installed beforehand.
```bash
git clone https://github.com/langchain-ai/agent-inbox.git
cd agent-inbox
yarn install
```
--------------------------------
### ThreadsProvider Setup and Usage
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Sets up the ThreadsProvider at the app root and demonstrates consuming its context via useThreadsContext to manage thread data and invoke actions. It automatically re-fetches threads based on URL parameters and agent inbox changes.
```tsx
import { ThreadsProvider, useThreadsContext } from "@/components/agent-inbox/contexts/ThreadContext";
import { HumanResponse } from "@/components/agent-inbox/types";
// --- Provider setup (once, at app root) ---
function App() {
return (
);
}
// --- Consumer: read threads and invoke actions ---
function MyInboxUI() {
const {
loading,
threadData,
hasMoreThreads,
agentInboxes,
fetchThreads,
fetchSingleThread,
sendHumanResponse,
ignoreThread,
clearThreadData,
addAgentInbox,
deleteAgentInbox,
changeAgentInbox,
updateAgentInbox,
} = useThreadsContext();
// Fetch interrupted threads
const loadInterrupted = () => fetchThreads("interrupted");
// Send a streamed response and consume events
const submitAndStream = async (threadId: string, response: HumanResponse) => {
const stream = sendHumanResponse(threadId, [response], { stream: true });
if (!stream) return;
for await (const chunk of stream) {
if (chunk.data?.event === "on_chain_start") {
console.log("Node executing:", chunk.data.metadata?.langgraph_node);
}
if (chunk.event === "error") {
console.error("Stream error:", chunk.data);
}
}
};
// Non-streaming response
const submitSync = (threadId: string, response: HumanResponse) => {
const run = sendHumanResponse(threadId, [response]);
run?.then((r) => console.log("Run created:", r.run_id));
};
return loading ?
Loading...
:
{threadData.map(t =>
{t.status}
)}
;
}
```
--------------------------------
### Python Example: Using the interrupt function
Source: https://github.com/langchain-ai/agent-inbox/blob/main/README.md
Demonstrates how to create and send a `HumanInterrupt` request and process the `HumanResponse` in Python. Ensure the `interrupt` function is imported from `langgraph.types`.
```python
from typing import TypedDict, Literal, Optional, Union
from langgraph.types import interrupt
def my_graph_function(state: MyGraphState):
# Extract the last tool call from the `messages` field in the state
tool_call = state["messages"][-1].tool_calls[0]
# Create an interrupt
request: HumanInterrupt = {
"action_request": {
"action": tool_call['name'],
"args": tool_call['args']
},
"config": {
"allow_ignore": True,
"allow_respond": True,
"allow_edit": False,
"allow_accept": False
},
"description": _generate_email_markdown(state) # Generate a detailed markdown description.
}
# Send the interrupt request, and extract the first response.
# The Agent Inbox will always respond with a list of `HumanResponse` objects, although
# at this time only a single object will be returned.
response = interrupt(request)[0]
if response['type'] == "response":
# Do something with the response
# ...rest of function
```
--------------------------------
### TypeScript Example: Using the interrupt function
Source: https://github.com/langchain-ai/agent-inbox/blob/main/README.md
Shows how to use the `interrupt` function to send a `HumanInterrupt` and receive a `HumanResponse` in TypeScript. Import `interrupt`, `HumanInterrupt`, and `HumanResponse` from `@langchain/langgraph`.
```typescript
import { interrupt } from "@langchain/langgraph";
import { HumanInterrupt, HumanResponse } from "@langchain/langgraph/prebuilt";
function myGraphFunction(state: MyGraphState) {
// Extract the last tool call from the `messages` field in the state
const toolCall = state.messages[state.messages.length - 1].tool_calls[0];
// Create an interrupt
const request: HumanInterrupt = {
action_request: {
action: toolCall.name,
args: toolCall.args
},
config: {
allow_ignore: true,
allow_respond: true,
allow_edit: false,
allow_accept: false
},
description: _generateEmailMarkdown(state) // Generate a detailed markdown description.
};
// Send the interrupt request, and extract the first response.
// The Agent Inbox will always respond with an array of `HumanResponse` objects, although
// at this time only a single object will be returned.
const response = interrupt(request)[0];
if (response.type === "response") {
// Do something with the response
}
// ...rest of function
};
```
--------------------------------
### createClient
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Creates a configured `@langchain/langgraph-sdk` Client instance. It wraps the LangGraph SDK `Client` constructor with deployment URL and optional API key. The key is sent as an `x-api-key` header. Local deployments (non-HTTPS / localhost) do not require an API key.
```APIDOC
## `createClient`
**Creates a configured `@langchain/langgraph-sdk` Client instance.**
Wraps the LangGraph SDK `Client` constructor with deployment URL and optional API key. The key is sent as `x-api-key` header. Local deployments (non-HTTPS / localhost) do not require an API key.
```typescript
import { createClient } from "@/lib/client";
// For a deployed LangGraph Platform instance
const deployedClient = createClient({
deploymentUrl: "https://my-agent.default.us.langgraph.app",
langchainApiKey: "lsv2_pt_abc123...",
});
// For a local LangGraph server (no key required)
const localClient = createClient({
deploymentUrl: "http://localhost:2024",
langchainApiKey: undefined,
});
// Direct SDK usage after creation
const threads = await deployedClient.threads.search({
status: "interrupted",
offset: 0,
limit: 10,
metadata: { graph_id: "my_graph" },
});
const state = await deployedClient.threads.getState("thread-uuid");
// Resume an interrupted thread
const run = await deployedClient.runs.create("thread-uuid", "my_graph", {
command: { resume: [{ type: "accept", args: null }] },
});
// Streaming resume
const stream = deployedClient.runs.stream("thread-uuid", "my_graph", {
command: { resume: [{ type: "response", args: "Please proceed." }] },
streamMode: "events",
});
for await (const event of stream) {
console.log(event);
}
```
```
--------------------------------
### Create LangGraph Client
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Use `createClient` to instantiate a LangGraph SDK client. Provide the deployment URL and an optional API key for deployed instances. Local deployments do not require an API key. The key is sent as an `x-api-key` header.
```typescript
import { createClient } from "@/lib/client";
// For a deployed LangGraph Platform instance
const deployedClient = createClient({
deploymentUrl: "https://my-agent.default.us.langgraph.app",
langchainApiKey: "lsv2_pt_abc123...",
});
// For a local LangGraph server (no key required)
const localClient = createClient({
deploymentUrl: "http://localhost:2024",
langchainApiKey: undefined,
});
// Direct SDK usage after creation
const threads = await deployedClient.threads.search({
status: "interrupted",
offset: 0,
limit: 10,
metadata: { graph_id: "my_graph" },
});
const state = await deployedClient.threads.getState("thread-uuid");
// Resume an interrupted thread
const run = await deployedClient.runs.create("thread-uuid", "my_graph", {
command: { resume: [{ type: "accept", args: null }] },
});
// Streaming resume
const stream = deployedClient.runs.stream("thread-uuid", "my_graph", {
command: { resume: [{ type: "response", args: "Please proceed." }] },
streamMode: "events",
});
for await (const event of stream) {
console.log(event);
}
```
--------------------------------
### Fetch Deployment Info from LangGraph
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Fetches metadata from a LangGraph deployment's `/info` endpoint to retrieve `project_id` and `tenant_id`. Returns `null` on any error. Used for generating stable inbox IDs.
```typescript
import { fetchDeploymentInfo } from "@/components/agent-inbox/utils";
const info = await fetchDeploymentInfo("https://my-agent.default.us.langgraph.app");
if (info) {
console.log(info.host.project_id); // "a1b2c3d4-மையில்"
console.log(info.host.tenant_id); // "t9z8y7..."
console.log(info.host.revision_id); // "rev_abc"
console.log(info.flags.langsmith); // true
}
// Generate the inbox ID in the new format
if (info?.host.project_id) {
const inboxId = `${info.host.project_id}:my_graph`;
// => "a1b2c3d4-...:my_graph"
}
```
--------------------------------
### AddAgentInboxDialog Component Usage
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Demonstrates different ways to use the AddAgentInboxDialog component, including standard triggering, hiding the built-in trigger, and providing an API key for deployed graph onboarding. The LangSmith API key field appears automatically under specific URL and deployment conditions.
```tsx
import { AddAgentInboxDialog } from "@/components/agent-inbox/components/add-agent-inbox-dialog";
import { useState } from "react";
function SettingsPanel() {
const [apiKey, setApiKey] = useState("");
return (
{/* Standard trigger button */}
{/* Hide built-in trigger (controlled externally) */}
{/* With API key field for deployed graph onboarding */}
setApiKey(e.target.value)}
/>
{/* The LangSmith API key field appears automatically when:
- no_inboxes_found=true is in the URL, AND
- the entered deployment URL is a deployed (HTTPS, non-localhost) URL */}
);
}
// First-time user flow (triggered automatically):
// URL: /?no_inboxes_found=true → dialog opens with welcome message
// After adding an inbox: → no_inboxes_found param is cleared, page reloads
```
--------------------------------
### Convert LangChain Messages to UI and OpenAI Formats
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Use `convertLangchainMessages` for rendering in `@assistant-ui/react` and `convertToOpenAIFormat` for LLM API calls. Both functions require importing from '@/lib/convert_messages'.
```typescript
import {
convertLangchainMessages,
convertToOpenAIFormat,
getMessageType,
} from "@/lib/convert_messages";
import { HumanMessage, AIMessage, ToolMessage, SystemMessage } from "@langchain/core/messages";
const messages = [
new SystemMessage("You are a helpful assistant."),
new HumanMessage("What's the weather?"),
new AIMessage({ content: "", tool_calls: [{ id: "tc_1", name: "get_weather", args: { city: "NYC" } }] }),
new ToolMessage({ content: "72°F and sunny", tool_call_id: "tc_1", name: "get_weather" }),
new AIMessage("It's 72°F and sunny in NYC."),
];
// For @assistant-ui/react rendering
const uiMessages = messages.map(m => convertLangchainMessages(m));
// [
// { role: "system", content: [{ type: "text", text: "You are a helpful assistant." }] },
// { role: "user", content: [{ type: "text", text: "What's the weather?" }] },
// { role: "assistant", content: [{ type: "tool-call", toolCallId: "tc_1", toolName: "get_weather", args: {...} }, { type: "text", text: "" }] },
// { role: "tool", toolCallId: "tc_1", toolName: "get_weather", result: "72°F and sunny" },
// { role: "assistant", content: [{ type: "text", text: "It's 72°F and sunny in NYC." }] },
// ]
// For OpenAI API calls
const openAiMessages = messages.map(convertToOpenAIFormat);
// [
// { role: "system", content: "You are a helpful assistant." },
// { role: "user", content: "What's the weather?" },
// { role: "assistant", content: "" },
// { role: "tool", toolName: "get_weather", result: "72°F and sunny" },
// { role: "assistant", content: "It's 72°F and sunny in NYC." },
// ]
// Safely detect message type from any LangChain message variant
const type = getMessageType(new HumanMessage("hi")); // => "human"
```
--------------------------------
### Create Default Human Response and Detect Changes
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Builds the initial `HumanResponseWithEdits[]` array and determines the default submit type. It also initializes a ref for change detection. Priority for `defaultSubmitType` is `accept` > `response` > `edit`. Use `haveArgsChanged` to check if arguments have been modified.
```typescript
import { createDefaultHumanResponse } from "@/components/agent-inbox/utils";
import { HumanInterrupt } from "@/components/agent-inbox/types";
import { useRef } from "react";
const interrupt: HumanInterrupt = {
action_request: { action: "draft_email", args: { subject: "Hello", body: "World" } },
config: { allow_accept: true, allow_edit: true, allow_respond: false, allow_ignore: true },
};
const initialValues = { current: {} as Record };
const { responses, defaultSubmitType, hasAccept } = createDefaultHumanResponse(
[interrupt],
initialValues
);
// responses => [
// { type: "edit", args: { action: "draft_email", args: {...} }, acceptAllowed: true, editsMade: false },
// { type: "ignore", args: null },
// { type: "accept", args: null },
// ]
// defaultSubmitType => "accept"
// hasAccept => true
// initialValues.current => { subject: "Hello", body: "World" }
// Check if args have been changed by the user
import { haveArgsChanged } from "@/components/agent-inbox/utils";
const changed = haveArgsChanged(
{ subject: "Hi there", body: "World" },
initialValues.current
);
// changed => true (subject differs)
```
--------------------------------
### Manage URL Search Parameters with useQueryParams
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Use this hook to read and update URL search parameters without full page navigation. It leverages Next.js `router.replace` and reads directly from `window.location.href` to prevent stale closure issues.
```tsx
import { useQueryParams } from "@/components/agent-inbox/hooks/use-query-params";
import {
INBOX_PARAM,
OFFSET_PARAM,
LIMIT_PARAM,
AGENT_INBOX_PARAM,
VIEW_STATE_THREAD_QUERY_PARAM,
} from "@/components/agent-inbox/constants";
function PaginationControls() {
const { searchParams, updateQueryParams, getSearchParam } = useQueryParams();
const currentOffset = Number(getSearchParam(OFFSET_PARAM) ?? "0");
const currentLimit = Number(getSearchParam(LIMIT_PARAM) ?? "10");
// Advance one page
const nextPage = () =>
updateQueryParams(OFFSET_PARAM, String(currentOffset + currentLimit));
// Go back one page
const prevPage = () =>
updateQueryParams(OFFSET_PARAM, String(Math.max(0, currentOffset - currentLimit)));
// Change both offset and limit atomically
const setPageSize = (limit: number) =>
updateQueryParams([OFFSET_PARAM, LIMIT_PARAM], ["0", String(limit)]);
// Open a thread detail view
const openThread = (threadId: string) =>
updateQueryParams(VIEW_STATE_THREAD_QUERY_PARAM, threadId);
// Navigate back to inbox list (removes the thread param)
const closeThread = () =>
updateQueryParams(VIEW_STATE_THREAD_QUERY_PARAM); // no value = delete
return (
Offset: {currentOffset}
);
}
```
--------------------------------
### Construct LangSmith Studio URL
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Generates a LangSmith Studio URL for inspecting a thread. Handles both deployed and local graphs, appending `baseUrl` as a query parameter for local deployments.
```typescript
import { constructOpenInStudioURL } from "@/components/agent-inbox/utils";
import { AgentInbox } from "@/components/agent-inbox/types";
// Deployed graph
const deployedInbox: AgentInbox = {
id: "proj-uuid:my_graph",
graphId: "my_graph",
deploymentUrl: "https://my-agent.default.us.langgraph.app",
tenantId: "tenant-uuid",
selected: true,
createdAt: "2024-01-01T00:00:00Z",
};
const deployedUrl = constructOpenInStudioURL(deployedInbox, "thread-abc-123");
// => "https://smith.langchain.com/studio/thread?organizationId=tenant-uuid&hostProjectId=proj-uuid&threadId=thread-abc-123"
// Local graph
const localInbox: AgentInbox = {
id: "local-uuid",
graphId: "my_graph",
deploymentUrl: "http://localhost:2024",
selected: true,
createdAt: "2024-01-01T00:00:00Z",
};
const localUrl = constructOpenInStudioURL(localInbox, "thread-abc-123");
// => "https://smith.langchain.com/studio/thread?threadId=thread-abc-123&baseUrl=http%3A%2F%2Flocalhost%3A2024"
window.open(localUrl, "_blank");
```
--------------------------------
### Integrate AgentInbox Component
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Integrates the AgentInbox component into your application. Ensure it is wrapped within ThreadsProvider and Suspense for proper context and loading state management. Optionally, provide a generic type for typed thread state.
```tsx
"use client";
import { AgentInbox } from "@/components/agent-inbox";
import { ThreadsProvider } from "@/components/agent-inbox/contexts/ThreadContext";
import { Suspense } from "react";
export default function Page() {
return (
Loading...}>
{/* Optionally pass custom ThreadValues generic for typed thread state */}
/>
);
}
// URL states managed automatically:
// List view: /?agent_inbox=&inbox=interrupted&offset=0&limit=10
// Thread view: /?agent_inbox=&inbox=interrupted&offset=0&limit=10&view_state_thread_id=
```
--------------------------------
### SSR-Safe Browser localStorage with useLocalStorage
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
This hook provides a server-side rendering-safe wrapper around the browser's `localStorage`. It guards all calls with `typeof window === "undefined"` to prevent errors in Next.js server components or during SSR. It returns `undefined` or `null` on the server or in test environments.
```tsx
import { useLocalStorage } from "@/components/agent-inbox/hooks/use-local-storage";
import { LANGCHAIN_API_KEY_LOCAL_STORAGE_KEY } from "@/components/agent-inbox/constants";
function ApiKeyManager() {
const { getItem, setItem, removeItem } = useLocalStorage();
// Store the LangSmith API key
const saveKey = (key: string) =>
setItem(LANGCHAIN_API_KEY_LOCAL_STORAGE_KEY, key);
// Read it back (returns null if not set, undefined if SSR)
const loadKey = (): string | null | undefined =>
getItem(LANGCHAIN_API_KEY_LOCAL_STORAGE_KEY);
// Clear it
const clearKey = () =>
removeItem(LANGCHAIN_API_KEY_LOCAL_STORAGE_KEY);
// Custom JSON storage pattern
const storeObject = (data: Record) =>
setItem("my_key", JSON.stringify(data));
const loadObject = (fallback: T): T => {
const raw = getItem("my_key");
if (!raw) return fallback;
try { return JSON.parse(raw) as T; }
catch { return fallback; }
};
return (
);
}
```
--------------------------------
### Run Inbox ID Backfill
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Migrates existing inbox IDs to the projectId:graphId format. Runs once per user session. Use `forceInboxBackfill` to re-run unconditionally.
```typescript
import {
runInboxBackfill,
forceInboxBackfill,
isBackfillCompleted,
clearBackfillFlag,
} from "@/components/agent-inbox/utils/backfill";
// Normal startup: runs only if not yet completed
const result = await runInboxBackfill();
if (result.success) {
console.log("Updated inboxes:", result.updatedInboxes);
// Each deployed inbox now has id: "projectId:graphId"
}
// Force re-run (useful after adding a new inbox or debugging)
const forced = await forceInboxBackfill();
console.log("Force backfill succeeded:", forced.success);
// Check status
console.log("Backfill done?", isBackfillCompleted()); // true after first successful run
// Reset for testing
clearBackfillFlag();
console.log("Backfill done?", isBackfillCompleted()); // false
// Browser console helpers (exposed on window)
// window.resetInboxData() — shows debug info and optionally clears all inbox data
// window.forceBackfill() — same as forceInboxBackfill()
```
--------------------------------
### useInboxes
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Hook for full CRUD management of agent inboxes stored in localStorage. Runs a one-time backfill on mount to migrate inbox IDs to the `projectId:graphId` format for deployed graphs. All changes are persisted to `localStorage` key `inbox:agent_inboxes` and reflected in URL query params.
```APIDOC
## `useInboxes`
**Hook for full CRUD management of agent inboxes stored in localStorage.**
Runs a one-time backfill on mount to migrate inbox IDs to the `projectId:graphId` format for deployed graphs. All changes are persisted to `localStorage` key `inbox:agent_inboxes` and reflected in URL query params.
```tsx
import { useInboxes } from "@/components/agent-inbox/hooks/use-inboxes";
import { AgentInbox } from "@/components/agent-inbox/types";
function InboxManager() {
const {
agentInboxes, // AgentInbox[] — reactive list from localStorage
addAgentInbox, // Add and auto-select a new inbox
deleteAgentInbox, // Remove by id; selects first remaining
changeAgentInbox, // Select a different inbox (updates URL + localStorage)
updateAgentInbox, // Edit an existing inbox in-place
} = useInboxes();
// Add a new local-dev inbox
const handleAdd = () => {
addAgentInbox({
id: crypto.randomUUID(),
graphId: "my_email_agent",
deploymentUrl: "http://localhost:2024",
name: "Local Email Agent",
selected: false,
createdAt: new Date().toISOString(),
});
};
// Switch to a different inbox (resets offset/limit/inbox tab)
const handleSwitch = (id: string) => changeAgentInbox(id);
// Update an existing inbox (e.g., rename)
const handleRename = (inbox: AgentInbox) => {
updateAgentInbox({ ...inbox, name: "Renamed Agent" });
};
return (
{agentInboxes.map(inbox => (
{inbox.name ?? inbox.graphId}
))}
);
}
```
```
--------------------------------
### Manage Agent Inboxes with `useInboxes` Hook
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
The `useInboxes` hook provides full CRUD management for agent inboxes stored in localStorage. It performs a one-time backfill on mount to migrate inbox IDs to the `projectId:graphId` format for deployed graphs. All changes are persisted to `localStorage` key `inbox:agent_inboxes` and reflected in URL query params.
```tsx
import { useInboxes } from "@/components/agent-inbox/hooks/use-inboxes";
import { AgentInbox } from "@/components/agent-inbox/types";
function InboxManager() {
const {
agentInboxes, // AgentInbox[] — reactive list from localStorage
addAgentInbox, // Add and auto-select a new inbox
deleteAgentInbox, // Remove by id; selects first remaining
changeAgentInbox, // Select a different inbox (updates URL + localStorage)
updateAgentInbox, // Edit an existing inbox in-place
} = useInboxes();
// Add a new local-dev inbox
const handleAdd = () => {
addAgentInbox({
id: crypto.randomUUID(),
graphId: "my_email_agent",
deploymentUrl: "http://localhost:2024",
name: "Local Email Agent",
selected: false,
createdAt: new Date().toISOString(),
});
};
// Switch to a different inbox (resets offset/limit/inbox tab)
const handleSwitch = (id: string) => changeAgentInbox(id);
// Update an existing inbox (e.g., rename)
const handleRename = (inbox: AgentInbox) => {
updateAgentInbox({ ...inbox, name: "Renamed Agent" });
};
return (
{agentInboxes.map(inbox => (
{inbox.name ?? inbox.graphId}
))}
);
}
```
--------------------------------
### Manage User Interaction State with useInterruptedActions
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
This hook manages all user interaction state for a single interrupted thread. It initializes human response state, determines the default submit type, and provides handlers for submission, ignoring, and resolving. Use this hook to stream graph execution after submission and refetch thread state on completion.
```tsx
import useInterruptedActions from "@/components/agent-inbox/hooks/use-interrupted-actions";
import { InterruptedThreadData, ThreadData } from "@/components/agent-inbox/types";
import { useState } from "react";
function InterruptHandler({ threadData }: { threadData: InterruptedThreadData }) {
const [data, setData] = useState(threadData);
const {
handleSubmit,
handleIgnore,
handleResolve,
humanResponse,
setHumanResponse,
selectedSubmitType,
setSelectedSubmitType,
loading,
streaming,
streamFinished,
currentNode,
hasEdited,
hasAddedResponse,
acceptAllowed,
isIgnoreAllowed,
supportsMultipleMethods,
initialHumanInterruptEditValue,
} = useInterruptedActions({ threadData, setThreadData: setData });
return (
{streaming &&
Executing node: {currentNode}...
}
{streamFinished &&
Graph run complete.
}
{supportsMultipleMethods && (
)}
{selectedSubmitType === "response" && (
);
}
```
--------------------------------
### Python Interrupt Schema Definition
Source: https://github.com/langchain-ai/agent-inbox/blob/main/README.md
Defines the Python type hints for interrupt configurations and responses. Used to structure interrupt data for LangGraph compatibility.
```python
class HumanInterruptConfig(TypedDict):
allow_ignore: bool
allow_respond: bool
allow_edit: bool
allow_accept: bool
class ActionRequest(TypedDict):
action: str
args: dict
class HumanInterrupt(TypedDict):
action_request: ActionRequest
config: HumanInterruptConfig
description: Optional[str]
class HumanResponse(TypedDict):
type: Literal['accept', 'ignore', 'response', 'edit']
args: Union[None, str, ActionRequest]
```
--------------------------------
### TypeScript Interfaces for Agent Inbox
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Defines the core TypeScript interfaces for data contracts between the UI and LangGraph SDK, including interrupts, responses, threads, and inbox configuration. These types govern the flow of information for human-in-the-loop interactions.
```typescript
import {
HumanInterrupt,
HumanInterruptConfig,
ActionRequest,
HumanResponse,
HumanResponseWithEdits,
ThreadData,
InterruptedThreadData,
GenericThreadData,
AgentInbox,
ThreadStatusWithAll,
SubmitType,
} from "@/components/agent-inbox/types";
// --- Interrupt sent FROM your LangGraph agent ---
const interrupt: HumanInterrupt = {
action_request: {
action: "send_email", // Rendered as title in the UI
args: {
to: "user@example.com",
subject: "Quarterly report",
body: "Please find attached...",
},
},
config: {
allow_ignore: true, // User can discard the thread
allow_respond: true, // User can send a text reply
allow_edit: true, // User can modify args before accepting
allow_accept: true, // User can approve args unchanged
},
description: "## Review Email\nThe agent wants to send the email above. Please review before proceeding.",
};
// --- Response sent BACK to your LangGraph agent ---
const acceptResponse: HumanResponse = { type: "accept", args: null };
const editResponse: HumanResponse = {
type: "edit",
args: { action: "send_email", args: { to: "user@example.com", subject: "Updated subject", body: "..." } },
};
const textResponse: HumanResponse = { type: "response", args: "Please revise the body." };
const ignoreResponse: HumanResponse = { type: "ignore", args: null };
// --- Inbox configuration (stored in localStorage) ---
const inbox: AgentInbox = {
id: "proj-uuid:my_graph", // Auto-generated; format:projectId:graphId for deployed graphs
graphId: "my_graph",
deploymentUrl: "https://my-agent.default.us.langgraph.app",
name: "Email Agent",
selected: true,
tenantId: "tenant-uuid", // Populated automatically for deployed graphs
createdAt: new Date().toISOString(),
};
// --- Thread discriminated union ---
const interrupted: InterruptedThreadData = {
thread: { thread_id: "abc123", status: "interrupted", created_at: "...", updated_at: "...", values: {} },
status: "interrupted",
interrupts: [interrupt],
invalidSchema: false,
};
const generic: GenericThreadData = {
thread: { thread_id: "def456", status: "idle", created_at: "...", updated_at: "...", values: {} },
status: "idle",
};
// Filter type
const statusFilter: ThreadStatusWithAll = "interrupted"; // | "idle" | "busy" | "error" | "all" | "human_response_needed"
```
--------------------------------
### Development-Only Console Logger
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
The `logger` utility from '@/components/agent-inbox/utils/logger' acts as a drop-in replacement for `console` methods but is silenced in production environments. This prevents debug output from leaking into production builds.
```typescript
import { logger } from "@/components/agent-inbox/utils/logger";
// All methods are silenced when process.env.NODE_ENV === "production"
logger.log("Fetching threads with params:", { offset: 0, limit: 10 });
// => logs in dev, silent in prod
logger.error("Failed to parse inbox data:", new SyntaxError("Unexpected token"));
// => console.error in dev, silent in prod
logger.warn("Inbox ID missing colon separator, falling back to UUID");
logger.debug("Raw interrupt payload:", rawThread.interrupts);
// Conditionally log only in development
if (process.env.NODE_ENV !== "production") {
logger.log("Detailed interrupt structure:", JSON.stringify(interrupt, null, 2));
}
```
--------------------------------
### Save and Restore Scroll Position with useScrollPosition
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
This hook helps manage scroll position persistence when navigating between list and thread views. It uses a ref to store the scroll offset without triggering re-renders and detects whether to save/restore window scroll or a specific container's scroll, using `requestAnimationFrame` for accurate timing.
```tsx
import { useScrollPosition } from "@/components/agent-inbox/hooks/use-scroll-position";
import { useRef } from "react";
function ScrollableList() {
const containerRef = useRef(null);
const { saveScrollPosition, restoreScrollPosition } = useScrollPosition();
// Save before navigating away
const handleItemClick = () => {
if (containerRef.current?.scrollTop) {
saveScrollPosition(containerRef.current); // save container scroll
} else {
saveScrollPosition(); // save window scroll
}
// ... navigate to thread detail
};
// Restore when returning (e.g., in useLayoutEffect)
const handleReturnToList = () => {
restoreScrollPosition(containerRef.current); // smooth-scrolls back
};
return (
{Array.from({ length: 100 }, (_, i) => (
Thread {i}
))}
);
}
```
--------------------------------
### TypeScript Interrupt Schema Definition
Source: https://github.com/langchain-ai/agent-inbox/blob/main/README.md
Defines the TypeScript interfaces for interrupt configurations and responses. Used to structure interrupt data for LangGraph compatibility.
```typescript
export interface HumanInterruptConfig {
allow_ignore: boolean;
allow_respond: boolean;
allow_edit: boolean;
allow_accept: boolean;
}
export interface ActionRequest {
action: string;
args: Record;
}
export interface HumanInterrupt {
action_request: ActionRequest;
config: HumanInterruptConfig;
description?: string;
}
export type HumanResponse = {
type: "accept" | "ignore" | "response" | "edit";
args: null | string | ActionRequest;
};
```
--------------------------------
### Process Interrupted Thread
Source: https://context7.com/langchain-ai/agent-inbox/llms.txt
Extracts and normalizes `HumanInterrupt[]` from a LangGraph SDK `Thread` object. Handles multiple interrupt payload formats and falls back to `IMPROPER_SCHEMA` on parse failure.
```typescript
import {
getInterruptFromThread,
processInterruptedThread,
processThreadWithoutInterrupts,
getThreadFilterMetadata,
} from "@/components/agent-inbox/contexts/utils";
import { Thread } from "@langchain/langgraph-sdk";
const thread: Thread = {
thread_id: "abc-123",
status: "interrupted",
interrupts: {
"__interrupt__": [{ value: { action_request: { action: "send_email", args: {} }, config: { allow_accept: true, allow_edit: true, allow_respond: false, allow_ignore: true } } }]
},
created_at: "2024-01-01T00:00:00Z",
updated_at: "2024-01-01T00:01:00Z",
values: {},
};
// Extract interrupts directly from thread
const interrupts = getInterruptFromThread(thread);
// => [{ action_request: { action: "send_email", args: {} }, config: {...} }]
// Full processing: returns ThreadData with invalidSchema flag
const threadData = processInterruptedThread(thread);
// => { thread, interrupts, status: "interrupted", invalidSchema: false }
// Build metadata filter for threads.search() call
const metadata = getThreadFilterMetadata([
{ id: "uuid", graphId: "my_graph", deploymentUrl: "...", selected: true, createdAt: "..." }
]);
// => { graph_id: "my_graph" } (or { assistant_id: "..." } if graphId is a UUID)
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.