Agent Inbox: A Browser UI for LangGraph Interrupts
📥 An inbox UX for interacting with human-in-the-loop agents.
At a glance
- What is it?
- Agent Inbox is a TypeScript front end that lists pending LangGraph interrupts, lets a human accept, edit, respond to or ignore them, and posts a HumanResponse back to the graph. It is a thin client over the interrupt protocol, and adopting it means reshaping the interrupt payloads your graph already emits.
- Who is it for?
- Adopt Agent Inbox if your graphs already pause through LangGraph's interrupt function and you want a shared review surface without building one. Skip it if your approval flow lives in Slack, email or a ticketing system, or if you cannot change the interrupt payloads your deployed graphs emit, because the inbox reads action_request, config and description and nothing else.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap Agent Inbox fills between a paused graph and a person
LangGraph can suspend a run mid-node and wait for input. That suspension is a state, not an interface. Without a UI, the pending interrupt sits in the checkpointer until someone calls the API by hand, inspects the payload and posts a response. Agent Inbox is that missing surface: a Next.js and TypeScript application that lists pending interrupts per configured graph and renders each one as a card with the action name as the header and the description below it. The audience is narrow and specific. It is for teams already running a LangGraph deployment who want a human reviewer to see a queue of decisions rather than a stream of logs. It assumes the reviewer is a person with a browser and a LangSmith API key, not an automated approver. The README points to a hosted instance at dev.agentinbox.ai for anyone who does not want to deploy it, and to two minimal example repositories, one in Python and one in TypeScript, for anyone who wants a working graph to point it at.
The HumanInterrupt contract the inbox actually reads
Agent Inbox does not inspect your graph's state schema. It reads one shape. A HumanInterrupt has three fields: action_request, config and an optional description. action_request carries an action string, rendered as the card header, and an args dictionary, described in the README as tool call arguments. config is four booleans: allow_ignore, allow_respond, allow_edit, allow_accept. Any combination is permitted, and the inbox only offers the buttons you enabled. description is optional, may be markdown, and the README recommends it for context and instructions. The response side is symmetrical. HumanResponse has a type of accept, ignore, response or edit, and an args field that is null, a string, or an ActionRequest depending on the type. The README states that the inbox always sends back a list containing a single HumanResponse object. The four types are not interchangeable. accept echoes the original action_request with every args value converted to a string. edit returns an ActionRequest with the same structure but stringified values carrying the user's changes. response returns a plain string and needs no arguments. ignore returns null. That stringification rule is the sharpest detail in the schema, and it is easy to miss when reading the type definitions alone.
Setup: clone, install, then configure in the browser
The prerequisites are Node.js, yarn, a running LangGraph deployment (local or on LangGraph Platform) and a LangGraph API key. The README also asks for a LangSmith API key during configuration, which is a separate credential from the deployment key and is the one you paste into the UI. Installation is three commands from the README: git clone https://github.com/langchain-ai/agent-inbox.git, cd agent-inbox, yarn install. There is no environment file documented for the inbox itself. Configuration happens inside the running application. You click Settings in the sidebar and enter your LangSmith API key. Then you open the settings popover at the bottom left inside the sidebar, click Add Inbox, and fill a dialog with three fields: Assistant/Graph ID (required), the graph name or assistant ID used when sending human responses back; Deployment URL (required), the LangGraph deployment the inbox fetches interrupts from and posts responses to; and Name (optional), a label. The README states these values are stored in the browser's local storage and are used only to connect and authenticate requests to the deployment. That has a practical consequence: the inbox configuration is per browser profile, not per deployment. A second reviewer on a second machine configures the same inbox again, and clearing site data removes it.
The interrupt function is a migration, not a config flag
The README is explicit that using Agent Inbox requires replacing every place you raise a NodeInterrupt exception with a call to LangGraph's interrupt function, passing a HumanInterrupt as the argument and expecting a HumanResponse as the return value. This is the real cost of adoption, and it is not a one-line change. Every interrupt site in your codebase has to be rewritten to construct the action_request, decide which of the four allow flags apply, and handle a response object whose args type varies by the response type. The README links a conceptual guide and a how-to guide for the interrupt function in the LangGraph documentation, and notes that TypeScript documentation is still coming, though it says the concepts and implementation are the same. A Python example is shown in the README: a graph function reads the last tool call from state["messages"], builds a HumanInterrupt whose action_request.action is the tool call name, and passes it to interrupt. The example is truncated in the README, so the handling of the returned HumanResponse is not shown there. You will need the LangGraph docs for that part.
Where the inbox model breaks down
The design assumes one reviewer, one browser and one inbox per graph. Nothing in the README describes assignment, claiming, or a lock that stops two people from acting on the same interrupt, and nothing describes notifications when a new interrupt arrives. If your workflow needs an interrupt to reach a specific person, or needs a record of who approved what, this is the wrong tool. The local-storage configuration is the second constraint. Because the LangSmith API key and deployment URL live in the browser, the inbox is a personal console rather than a shared service with server-side credentials. The stringification rule is the third. On accept and edit, args values are converted to strings, so a graph that expects an integer, a boolean or a nested object in args will receive a string and must parse it back. That is fine for tool call arguments that were already going to be serialised, and awkward for anything else. Finally, the README does not document pagination, retention or what happens to an interrupt after it is actioned, so treat the list as a working queue rather than an audit log.
What you would otherwise build, or use instead
The realistic alternative is not another inbox product. It is the approval surface your team already has. If your reviewers live in Slack, the interrupt is a message with buttons and the response is a webhook call back into the LangGraph API. That approach reuses existing identity, keeps the credentials on a server where you control them, and gives you the notification and threading behaviour for free. The difference in approach is where the state lives. Agent Inbox owns a queue in the browser and reads interrupts by polling your deployment; a Slack or ticketing integration pushes each interrupt into a system that already has routing and permissions, at the cost of writing and maintaining the bridge yourself. Agent Inbox gives you the rendering of action_request, description and the four allow flags without writing any UI. The bridge gives you routing and auditability without writing any UI either, but you write the glue. If your interrupts are few and your reviewers are engineers comfortable with the LangGraph API, neither is necessary: a script that lists pending interrupts and posts a response covers the same ground.
Licence, maintenance and what the repository does not tell you
Agent Inbox is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive licence, and it is the same licence LangGraph itself uses, so there is no copyleft obligation created by pointing the inbox at your deployment. This is a description of the licence text, not legal advice; have counsel review it if the deployment is commercially sensitive. On maintenance, the repository shows a recent push and no retrieved releases, which means there is no tagged version to pin and no changelog to read before upgrading. You track the main branch. Since the inbox is a standalone application rather than a library you import, an upgrade is a pull and a yarn install, and the risk is concentrated in the schema contract rather than in your graph code: if a future commit changes how HumanInterrupt fields are rendered or which response types are emitted, your interrupt sites have to follow. The README does not state a support policy, a versioning scheme or a compatibility matrix with LangGraph releases, so pin a commit hash if you deploy it and re-read the schema section on every pull.
Editorial conclusion
Adopt Agent Inbox if your graphs already pause through LangGraph's interrupt function and you want a shared review surface without building one. Skip it if your approval flow lives in Slack, email or a ticketing system, or if you cannot change the interrupt payloads your deployed graphs emit, because the inbox reads action_request, config and description and nothing else. Verify first that your LangGraph deployment is reachable from the browser and that your interrupts pass a HumanInterrupt rather than a bare NodeInterrupt, then check whether any of your args values are non-serialisable, since accept and edit stringify them.
Community notes