pedantic-graph-interrupt
Run interruptible Pydantic Graphs that can be interrupted and resumed.
Table of Contents
Use cases
- LLM AI chatbots implemented using pydantic-ai that need to obtain user input outside of the graph.
- Document processing workflows where an external approval or human involvement is required.
- Graphs that can run for a very long time, so their execution must be broken into smaller continuous chunks. Most often each chunk is executed in a background worker, when the graph is ready to resume its run.
- And more...
Installation
pip install pydantic-graph-interrupt
Concepts
InterruptNodeis a special node type that interrupts the graph execution.proceed()is an alternative tograph.run(). It can be used to both start the graph run from scratch or resume it after an interruption.
Usage
Define graph with interrupt nodes
"""graph.py"""
from dataclasses import dataclass, field
from pydantic_graph import BaseNode, End, GraphRunContext
from pydantic_graph_interrupt import InterruptibleGraph, InterruptNode, Required
@dataclass
class MyState:
user_name: str | None = None
messages: list[str] = field(default_factory=list)
@dataclass
class Greet(BaseNode[MyState]):
async def run(self, ctx: GraphRunContext[MyState]) -> "WaitForName":
ctx.state.messages.append("Hello, what is your name?")
return WaitForName()
@dataclass # ↓ This is an interrupt node
class WaitForName(InterruptNode[MyState]):
# ↓ This is a required field that must be provided to resume the graph
user_name: Annotated[str | None, Required] = None
async def run(self, ctx: GraphRunContext[MyState]) -> "Goodbye":
ctx.state.user_name = self.user_name
return Goodbye(user_name=self.user_name)
@dataclass
class Goodbye(BaseNode[MyState]):
user_name: str
async def run(self, ctx: GraphRunContext[MyState]) -> End:
ctx.state.messages.append(f"Goodbye, {self.user_name}!")
return End(ctx.state)
my_graph = InterruptibleGraph(nodes=[Greet, WaitForName, Goodbye])
Initialize persistence
When you just start, you have to initialize the persistence. This defines the starting node of the graph and sets correct types inside the persistence.
"""steps.py"""
from pathlib import Path
from pydantic_graph.persistence.file import FileStatePersistence
from .graph import MyState, my_graph, Greet
async def start():
persistence = FileStatePersistence(Path("offline_state.json"))
state = MyState()
await my_graph.initialize(Greet(), persistence=persistence, state=state)
Start the graph
"""main.py"""
from .steps import start
await start()
Metadata
Release files for pydantic-graph-interrupt 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydantic_graph_interrupt-0.1.0.tar.gz | 15.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pydantic_graph_interrupt-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.9 kB
Release files / pydantic_graph_interrupt-0.1.0.tar.gz
| Download URL | pydantic_graph_interrupt-0.1.0.tar.gz |
|---|---|
| Size | 15.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fd065c197b4e3f327da49b55809e30980734f71ac7f5ac17fb87d597a3e9ac48
|
|
BLAKE2b-256 checksum How to use checksums |
2e67e4c86337f0da3b02fba0c0a0f59343e95d58bde308cddd9fe21bb8e57c34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.0
|
Release files / pydantic_graph_interrupt-0.1.0-py3-none-any.whl
| Download URL | pydantic_graph_interrupt-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4b46de6466244f83d8cbbc9c20ce6cfb584d7b80c7c2601a28b380f264f476b5
|
|
BLAKE2b-256 checksum How to use checksums |
48ade34e61e86db8ab28d6106575fa663fac7887feba2159273d7916e26c526f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.0
|