Skip to main content

welt-io-langgraph

pypi python

The LangGraph (Python) adapter for Welt's wire contract.

Install

uv add welt-io-langgraph

Usage

See examples/agent — the smallest complete agent built on this package (text streaming, tool use, file output, file input, and human-approval tools). The sections below explain the adapters it wires in.

API

The wire between Welt and the agent is JSON, specified by Welt's wire contract — plain LangGraph values do not fit it in either direction. Two functions adapt the inbound payload, three the outbound stream. The adapters target LangGraph 1.x and LangChain 1.x, whose messages carry standard content blocks.

Inbound

decode_messages(messages)

Turns Welt's Converse-shaped messages — built from the Slack thread, file bytes base64-encoded — into role/content message dicts that feed the graph input ({"messages": decoded}) as-is:

Converse block Standard content block
Text Text
Image Image
Document File (the document's name carried as filename)
Video Video

Each file-carrying block gets the media type LangChain models expect in place of the Converse format token, and the base64 data stays base64 — standard content blocks need no decoding. Malformed entries are skipped.

decode_interrupt_responses(responses)

Turns Welt's resume payload — a mapping of interrupt id to the answer a human chose — into the mapping Command(resume=...) takes, answering every pending interrupt at once:

agent.astream(
    Command(resume=decode_interrupt_responses(payload["interrupt_responses"])),
    config,
    stream_mode=["messages", "updates", "custom"],
)

The interrupt ids are LangGraph's own, as emitted by renderable_events; the config must point at the interrupted thread, which the host app stashes when an interrupt event goes by (see the example agent).

Outbound

renderable_events(stream)

Reduces the (mode, payload) items of astream(..., stream_mode=["messages", "updates", "custom"]) — whose values Welt does not render — to the events Welt renders:

LangGraph emits On the wire In the Slack thread
Token deltas data The streamed reply
Tool calls and tool messages current_tool_use / tool_result "Using tool" indicators (tool output stays off the wire)
Image / file / video content blocks a tool or the model returns file An uploaded file (size limits)
Pending interrupts interrupt Buttons and/or a text field

A run that stops for human input ends its stream with one interrupt event per pending interrupt; agents that do not use interrupts see no change.

file_event(name, data)

Builds the same file event from a filename and raw bytes, for attaching arbitrary files of your own. Yield it from the host app alongside the reduced stream, or pass it to LangGraph's custom stream writer to attach a file from inside a tool — renderable_events passes it through by itself:

writer = get_stream_writer()
writer(file_event("report.csv", csv_bytes))

interrupt_reason(message, options=..., input=...)

Builds the structured reason Welt renders as a message with the specified widgets — choice buttons (options), a free-text field (input), or both. The specs are the wire's own shapes; omitted fields keep Welt's defaults, and a typo becomes an immediate ValueError instead of a silent fallback to Welt's default rendering:

answer = interrupt(
    interrupt_reason(
        "Deploy to prod?",
        [
            {"value": "y", "label": "Deploy", "style": "primary"},
            {"value": "n", "label": "Cancel"},
        ],
        input={"label": "Or tell me what to do instead"},
    )
)

Working with interrupts

Welt's Interrupts doc covers the Slack side: how each reason renders, who can answer, multiple questions, and expiry. On the LangGraph side:

  • interrupt needs a checkpointer, even though the conversation history lives in Slack — pausing and resuming run through checkpoints. An in-memory checkpointer works on AgentCore Runtime, where each session keeps its own microVM.
  • Start each conversation turn on a fresh thread. Welt sends the whole Slack thread every turn by default, so letting the checkpointer stack turns into its own history would double the conversation. Resume alone reuses the interrupted thread's config. (An agent that keeps its own history instead sets AGENT_MANAGES_HISTORY on the Welt side.)
  • A plain interrupt value renders too. Any non-structured value — interrupt("Deploy to prod?") — becomes a question with Welt's default Approve / Deny buttons, whose answers arrive as y / n.
  • Code before interrupt runs again on resume. LangGraph re-executes the interrupted node (or tool) from its start, so wrap whatever precedes an interrupt and must not run twice — side effects, or work that must match what the human approved — in a LangGraph task: a completed task is not re-executed on resume; its saved result is reused. The example agent's sample_draft_report shows the pattern.

Supported Versions

Welt releases first; welt-io-langgraph follows, mirroring the minor version. While both are 0.x, a welt-io-langgraph 0.Y release supports Welt v0.Y — other combinations may work, but come with no guarantee.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

welt_io_langgraph-0.3.0.tar.gz (19.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

welt_io_langgraph-0.3.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file welt_io_langgraph-0.3.0.tar.gz.

File metadata

  • Download URL: welt_io_langgraph-0.3.0.tar.gz
  • Upload date:
  • Size: 19.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for welt_io_langgraph-0.3.0.tar.gz
Algorithm Hash digest
SHA256 e8809fd4422c81257ee9fdda8186788d22af383944383cccb70fbc3e902e134b
MD5 b5c6859ee81d60388aface3952b35f50
BLAKE2b-256 6948ec5ac5a0fdcb97c28daa05e5dd12500b9d42af5f4f0a51823ff1bba8a2aa

See more details on using hashes here.

File details

Details for the file welt_io_langgraph-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: welt_io_langgraph-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for welt_io_langgraph-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 60d9a0a4a4cb732522476ec9d3b2a4c05712724a6be413a7ce90f4b4385bea3d
MD5 139f1345dfe183ab680d8fc81e6cfc41
BLAKE2b-256 42e84f6ee072dd2a8c594acaaf8fabc0132432cc40b87943f8aefa567f8805d8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page