Changelog¶
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased changes live as changelog fragments
under changelog.d/ and are collated here on release with towncrier build.
1.1.0 - 2026-06-10¶
Changed¶
- The SQLite metadata store enables
journal_mode=WALand a 10 s busy timeout at setup, preventingdatabase is lockederrors when sharing a database file with the SQLite checkpointer. WAL persists in the database file once enabled. (#36) - Metadata store row shapes are now a typed contract:
ThreadRow/RunRowTypedDicts (exported fromskeino.persistence) replace thedict[str, Any]returns onMetadataStoreProtocol, and every backend now always includes theerrorkey on run rows (previously the in-memory store omitted it until a failure and kept stale values across status updates). HTTP responses are unchanged; customMetadataStoreProtocolimplementations should return the new shapes. (#36) - MongoDB: both the checkpointer and the metadata store now use the database
named in the
mongodb://…/<db>URI path, so graph state and metadata share the operator's chosen database. URIs without a path keep the previous defaults (checkpointing_dbfor checkpoints,skeinofor metadata). If your URI already names a database, both stores re-point to it on upgrade — existing data in the old default databases is not migrated. (#36)
Fixed¶
- PyPI trove classifier updated from
Development Status :: 4 - Betato5 - Production/Stableto match the stable 1.x release line. (#48) - Per-run token usage is now measured with a
UsageMetadataCallbackHandlerattached to each run's config, soX-Tokens-Usedand the streamingendevent report the run's own tokens — including for graphs that never store usage-bearing messages in checkpoint state (previously reported as 0), and without the cumulative over-count on multi-turn threads. Summing the final checkpoint's messages remains as a fallback for providers the handler can't see. (#52)
1.0.1 - 2026-06-10¶
Fixed¶
- Token-by-token
valuesstreaming now works for real langgraph-sdk clients. Two fixes: (1) the incremental accumulator engages whenvaluesis among the requested stream modes (SDK clients send["values", "messages-tuple", "custom"]), instead of only on an exact== ["values"]match that never fired — and it now forwardscustom(UI) events so generative-UI consumers don't regress; (2) output-schema value filtering introspects TypedDict output schemas (the commonStateGraph(State, output=OutputState)pattern) via__annotations__instead of failing closed and stripping every field — previously it droppedmessagesfrom every streamed event, so clients only saw the message after the post-run state fetch. Genuinely opaque schemas still fail closed. (#42)
1.0.0 - 2026-06-07¶
Added¶
- Pluggable, optional database backends selected by
checkpointer_scheme: SQLite (skeino[sqlite]), PostgreSQL (skeino[postgres]), and MongoDB (skeino[mongodb]) — each with a native durable metadata store (SqliteMetadataStore,MetadataStore,MongoMetadataStore) — plus a lazyredischeckpointer builder. All DB drivers are imported lazily, so the default install ships only the in-memory backend. (#25)
Changed¶
- Breaking: persistence is now scheme-authoritative.
checkpointer_scheme(default"memory") alone selects the backend for both the checkpointer and the metadata store; the newcheckpointer_uriis only the connection string for that scheme. A URI without a matching scheme is ignored (e.g.checkpointer_scheme="memory"with a Postgres URI still uses in-memory).langgraph.json'sstore.urinow maps tocheckpointer_uriwith the scheme derived from the URI prefix. (#25) - Adopted towncrier changelog fragments (
changelog.d/): contributors now add a per-change fragment instead of editingCHANGELOG.md, so concurrent PRs no longer conflict on the changelog. (#27)
Removed¶
- Breaking: removed the
postgres_uriandsqlite_pathsettings (which doubled as backend selectors) in favour ofcheckpointer_scheme+checkpointer_uri. PostgreSQL is no longer a hard dependency — installskeino[postgres]for it. (#25)
Fixed¶
skeino.__version__is now derived from the installed package metadata instead of a hard-coded literal that drifted out of sync withpyproject.toml(it had been stuck at0.1.0). (#35)
0.3.0 - 2026-06-07¶
Added¶
- Thread mutation & time-travel endpoints:
PATCH /threads/{id}(update metadata),DELETE /threads/{id}(delete the thread, its runs, and its checkpoints),POST /threads/{id}/state(human-in-the-loop state edit, returning the new checkpoint), and reads at a specific checkpoint viaGET /threads/{id}/state/{checkpoint_id}andPOST /threads/{id}/state/checkpoint. POST /threads/{thread_id}/copy(andThreadOps.copy) — fork a thread into an independent copy seeded with the source's latest state. Metadata is copied and stamped withforked_from. The copy is shallow (latest state only, not the full checkpoint history) and works across the in-memory and Postgres backends.
0.2.0 - 2026-06-07¶
Changed¶
- The
statusfilter onGET /threads/{id}/runsis now typed as theRunStatusliteral, so invalid values are rejected at the API edge with a 422 instead of by a hand-maintained membership check.
Fixed¶
- Assistant lookups no longer resolve an arbitrary valid UUID to the singleton assistant: only a supported id, the configured default id, or the assistant's deterministic UUID match; any other id returns 404.
- The
xray(/graph) andrecurse(/subgraphs) query parameters are now forwarded to LangGraph instead of being silently ignored, so the documented behaviour matches what the endpoints do. - Corrected the
from_langgraph_jsonmodule docstring:store.uriandhttp.corsare consumed;http.app,auth, anduiare ignored with a warning (previously it wrongly listedstoreas ignored and omittedui). - Output-schema filtering now fails closed: when a graph's declared output schema cannot be introspected, all state values are dropped (and the event is logged) instead of being passed through, preventing internal pipeline fields from leaking to API clients via thread state, history, and streaming.
- A checkpoint-read failure when building a thread response now preserves the
thread's stored status and logs a full traceback, instead of masking every
failure as
status="error"with empty values. RunEnrichingCheckpointerno longer copies the inner saver's__dict__over its own initialised state; it now initialises a single saver over the shared connection and delegates reads to the base class, removing two savers sharing mutable connection state.- Streaming runs no longer replay already-sent output when a transient error occurs mid-stream; retries are now confined to the window before the first event reaches the client, preventing duplicated output and double model invocations.
- The
reject/rollback/interruptmultitask strategies are now enforced for streaming runs: the thread lock is acquired before the run row is created, closing a race where concurrent streaming requests could all start and persist orphanpendingrows. - Client disconnects during a streaming run (
CancelledError) are no longer swallowed by the retry loop; the run is markedinterruptedand the thread lock is released. - A failed run's error-state persistence is now best-effort and never masks the
original exception or prevents the client from receiving the
errorevent. - Token usage for synchronous runs is now read while the thread lock is held, so an enqueued run can no longer report another run's totals; checkpoint-read failures during usage accounting are logged at error level.
- Run failures now log a full traceback (
exc_info) instead of just the message. - Threaded the
ThreadIfExists/RunIfNotExists/RunStatusliteral types through the metadata-store protocol and both implementations instead of widening them to barestrat the boundary, so mypy now verifies these closed value sets end to end. Removed the duplicated_RUN_LIST_STATUSESshadow constant.
0.1.0 - 2026-06-06¶
Added¶
- Initial public release.
create_app(graphs={...}, settings=...)— assemble a FastAPI app exposing a LangGraph Studio-compatible REST surface over any user-supplied graph.from_langgraph_json("langgraph.json")— load alanggraph.jsonand build the app.SkeinoSettings— typed configuration (persistence, assistant identity, streaming, server presentation, CORS).GraphRegistry— multi-graph registry (single-graph routed in v1).- Pluggable checkpointer registry with Postgres and in-memory implementations.
- Endpoints: threads, runs (incl. streaming/SSE), assistants, health/info.