langstage-cli
The terminal stage for your LangGraph agent. A Claude Code-style CLI that runs any LangGraph CompiledGraph — yours, not a bundled one — with streaming, tool-call rendering, and human-in-the-loop approval.
Renamed from deepagent-code (the old package name now just installs this one, and the
deepagent-codecommand still works). Not to be confused with LangChain'sdeepagents-code(dcode) — that's a separate project;langstage-cliis the terminal stage of the LangStage family.
Every stage for your LangGraph agent
langstage-cli is the terminal stage of the LangStage family: write your agent once — any LangGraph CompiledGraph — and run it on every stage with the same spec string (module:attr or path/to/file.py:attr), the same langstage.toml config file, and the same LANGSTAGE_* environment variables.
| Stage | Package | Try it |
|---|---|---|
| Web app | langstage | langstage run --agent my_agent.py:graph |
| JupyterLab | langstage-jupyter | pip install langstage-jupyter, then the chat sidebar in jupyter lab |
| Terminal | langstage-cli | you are here |
| VS Code | langstage-vscode | chat participant + stdio sidecar |
| Reference agent | langstage-hermes | LANGSTAGE_AGENT_SPEC=langstage_hermes.agent:graph on any stage |
| Shared core | langstage-core | typed events + config resolver behind every stage |
📖 Full documentation: https://dkedar7.github.io/langstage-docs/
Serve over AG-UI
This surface's agent — any LangGraph CompiledGraph — can also be served over the AG-UI protocol as a standalone HTTP endpoint:
pip install "langstage-core[agui]"
langstage-agui --agent my_agent.py:graph
Installation
pip install langstage-cli
Or install directly from GitHub:
pip install git+https://github.com/dkedar7/langstage-cli.git
Quick Start
No agent or API key yet? See the CLI working in one command:
langstage-cli --demo "hello"
Point it at your own agent (any LangGraph CompiledGraph):
export ANTHROPIC_API_KEY="your_api_key" # if your agent calls Anthropic
langstage-cli -a path/to/your_agent.py:graph
This launches an interactive conversation loop with your agent.
Usage
# Keyless demo agent — no API key, no agent of your own
langstage-cli --demo "Hello"
# Scaffold a runnable starter agent + langstage.toml (then just run it)
langstage-cli init
# Send a message directly to your agent
langstage-cli -a my_agent.py:graph "Hello, agent!"
# Specify a custom agent file
langstage-cli -a my_agent.py:graph
# Use a module path
langstage-cli -a mypackage.agents:chatbot
# Read message from a file
langstage-cli -f ./prompt.md
# Non-interactive mode (auto-approve tool calls)
langstage-cli --no-interactive
# Verbose output
langstage-cli -v
# Keyless demo agent (no API key needed)
langstage-cli --demo
# Print the resolved configuration: each value, its source, and the
# env var / langstage.toml key that sets it
langstage-cli --show-config
# Resume a previous conversation across separate invocations
langstage-cli "remember: my name is Kedar" # a fresh, PERSISTED session
langstage-cli -c "what's my name?" # continue the most recent session
langstage-cli --list-sessions # list resumable sessions
langstage-cli --resume <id> # resume a specific one
Getting started with your own agent
langstage-cli --demo "hi" # see the CLI work, keyless
langstage-cli init # scaffold my_agent.py + langstage.toml (your own graph)
langstage-cli "hi" # runs MY agent — no -a, no hand-editing
init writes a minimal, immediately-runnable starter agent (the stdlib StateGraph
example below — needs only langgraph, a base dependency) plus a langstage.toml
pointing at it, so the next langstage-cli "..." runs your graph. It refuses to
overwrite an existing my_agent.py / langstage.toml unless you pass --force.
Resuming a session
Every invocation persists its conversation to a durable, per-workspace store so a later run can pick it up — the terminal-agent continuity of Claude Code / Codex / Aider, without you baking a checkpointer into your own graph:
--continue/-c— resume the most recent session for this workspace and keep going. If there's no prior session, it just starts a fresh one.--resume <id>— resume a specific session (ids come from--list-sessions; a bare--resumealso lists them). A short prefix works if it's unambiguous.- A plain run with no flag starts a new session that is still persisted, so it can be continued later.
State lives in ~/.langstage/sessions/<workspace-hash>.sqlite (honoring
LANGSTAGE_CONFIG_HOME; override the whole location with LANGSTAGE_CLI_SESSIONS_DIR).
Persistence is on by default — disable it with --no-persist, LANGSTAGE_PERSIST=0, or
[session] persist = false in langstage.toml. A graph that compiles in its own
checkpointer keeps it (yours always wins); the CLI only supplies a durable one when your
graph has none. A pinned [configurable] thread_id now genuinely persists across runs.
--continue / --resume imply persistence over LANGSTAGE_PERSIST / [session] persist
(a CLI flag outranks them), but an explicit --no-persist on the same command line wins:
langstage-cli --no-persist -c "..." resumes the session read-only — the run sees the
prior conversation, but nothing is written back (no new turns, no index update, and no
store is created if none exists).
Commands
In the interactive loop:
/help(/h,/?) - Show this help message, or/help <command>for one command/status(/s) - Show session status (agent, thread, verbose, cwd)/version(/v) - Show version and the current agent/config(/cfg) - Show the resolved configuration, or set a runtime key:/config [key] [value]/verbose- Toggle verbose output, or set it explicitly:/verbose [on|off]/history(/hist) - Show recent conversation messages, optionally/history [N]/clear(/c) - Clear conversation history/reset(/restart) - Reset the session (clear history and start a new thread)/quit(/q,/exit) - Exit- Tab autocompletes commands; Ctrl+C exits
Environment Variables
# Agent location (path/to/file.py:variable_name or module:variable)
# (DEEPAGENT_AGENT_SPEC / DEEPAGENT_SPEC still accepted as deprecated aliases)
export LANGSTAGE_AGENT_SPEC="my_agent.py:graph"
langstage-cli
# Working directory
export LANGSTAGE_WORKSPACE_ROOT="/path/to/workspace"
Configuration Files
langstage-cli reads TOML config from two locations and merges them
(project overrides global):
- Global:
~/.langstage/config.toml - Project:
langstage.tomlin the current directory or any ancestor
Legacy locations (~/.deepagents/config.toml, deepagents.toml) are still
read as fallbacks; move your config when convenient — ~/.deepagents/ now
belongs to LangChain's dcode.
Precedence: CLI args > env vars > project TOML > global TOML > defaults.
Example langstage.toml:
[agent]
spec = "my_agent.py:graph"
[workspace]
root = "."
[ui]
verbose = true
[configurable]
# seeds LangGraph RunnableConfig.configurable
thread_id = "my-thread"
CLI Options
Usage: langstage-cli [OPTIONS] [MESSAGE]
Arguments:
MESSAGE Optional input to send to the agent immediately
Options:
-a, --agent TEXT Agent spec (path/to/file.py:graph or module:graph)
-g, --graph-name TEXT Graph variable name (default: "graph")
-f, --file PATH Read message from a file (any extension)
--interactive/--no-interactive Handle interrupts (default: interactive)
-v, --verbose Verbose output
--demo Run with the built-in keyless demo agent
--show-config Print the resolved configuration and exit
-q, --quiet Scriptable single-shot output: only the reply
--verify Preflight the agent (one real turn); exit 0/1
-c, --continue Resume the most recent session for this workspace
--resume [ID] Resume a specific session (bare: list them)
--list-sessions List resumable sessions for this workspace
--persist/--no-persist Persist this session so it can be continued (default: on)
--force For `init`: overwrite existing files
--version Show the version and exit
Subcommand:
init Scaffold my_agent.py + langstage.toml in the current dir
Verifying an agent (CI gate)
--verify loads the configured agent and runs one real turn, exiting 0 if it
completed cleanly and non-zero otherwise — so you can gate on it in CI before
trusting an agent. It catches a missing key, a broken tool, or a non-runnable graph
that a static "it imports" check would wave through (it runs the same
langstage-core preflight every LangStage surface uses):
langstage-cli --verify -a my_agent.py:graph || { echo "agent broken" >&2; exit 1; }
Scriptable output
A single-shot run (a MESSAGE argument or -f/--file) prints only the agent's
reply — no header, spinner, tool chatter, timing, or color — as soon as its output
is piped (stdout isn't a TTY). Errors and diagnostics go to stderr, and the
process exits non-zero if the turn failed, so a run is safe to capture:
answer=$(langstage-cli --demo "say hi") || echo "run failed" >&2
echo "$answer" # -> (demo agent) You said: say hi
Pass -q/--quiet to force the same clean output in a terminal.
Creating Your Own Agent
Your agent file just needs to export a compiled LangGraph graph — langstage-cli
runs any CompiledGraph. A minimal stdlib example (no extra deps):
# my_agent.py — needs only langgraph (a base dependency)
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
from langchain_core.messages import AIMessage
def respond(state):
last = state["messages"][-1].content
return {"messages": [AIMessage(content=f"You said: {last}")]}
g = StateGraph(MessagesState)
g.add_node("respond", respond)
g.add_edge(START, "respond")
g.add_edge("respond", END)
graph = g.compile()
Or a full deep agent (requires pip install deepagents):
# my_agent.py
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
agent = create_deep_agent(
name="My Agent",
model="anthropic:claude-sonnet-4-6",
checkpointer=MemorySaver(),
)
Then run it:
langstage-cli -a my_agent.py:graph # or :agent for the deepagents example
Programmatic Use
Since 1.0, streaming runs through the shared core's in-process AG-UI adapter
(pip install "langstage-core[agui]"):
import asyncio
from langstage_core import load_agent_spec
from langstage_core.agui import build_agent, iter_chunk_frames
agent = build_agent(load_agent_spec("my_agent.py:graph"))
async def main():
async for chunk in iter_chunk_frames(agent, "Hello!", thread_id="s1"):
if chunk.get("chunk"):
print(chunk["chunk"], end="")
asyncio.run(main())
License
MIT License - see LICENSE file for details.
Release files for langstage-cli 0.6.31
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| langstage_cli-0.6.31.tar.gz | 100.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langstage_cli-0.6.31-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 156.1 kB
Release files / langstage_cli-0.6.31.tar.gz
| Download URL | langstage_cli-0.6.31.tar.gz |
|---|---|
| Size | 100.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5784cb2ab82d5904d3fa87d06a5dcd453c7237a34bbf1c596af4747673245fb7
|
|
BLAKE2b-256 checksum How to use checksums |
5d5d10aa5b6cafe5076935c00b49565ffc9dc774484413b94d06ed05c7e561ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / langstage_cli-0.6.31-py3-none-any.whl
| Download URL | langstage_cli-0.6.31-py3-none-any.whl |
|---|---|
| Size | 55.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a2f71aa02c8933b4b225cf45f47582545f18b799b0af8bc60ea94e303ba117fd
|
|
BLAKE2b-256 checksum How to use checksums |
2d0735f48d015573974a7ba6786e73f82955c00ce5a09f26a3cea6c16bf2b4fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|