fix(*): three papercuts — interrupt_before resume, OCIModel ergonomics, AgentConfig.name + Tool.func#261
Merged
Merged
Conversation
…s, AgentConfig.name + Tool.func Bundles three small fixes that were filed together as separate issues. #258 — StateGraph.interrupt_before now durable - The pause boundary now writes through the checkpointer, so a follow-up ``execute(Command(resume=...))`` can recover the paused state across processes. Previously the inline ``interrupt()`` path saved but the ``interrupt_before`` path did not. - Resume no longer re-pauses at the same gate. On the first iteration after a resume, the gate check is skipped for the node we were paused on; subsequent iterations gate normally. - Both save sites (``interrupt_before`` and inline ``interrupt()``) now pack the graph-level state into ``AgentState.metadata`` instead of passing ``state=None``, which crashed the in-protocol checkpointers that call ``state.to_checkpoint()``. #259 — OCIModel region= and profile= aliases - ``region=`` builds the inference endpoint (``https://inference.generativeai.<region>.oci.oraclecloud.com``) when ``service_endpoint`` is not provided. Targets a cross-region model without typing out the full URL. - ``profile=`` is now an explicit alias for ``profile_name=``. Previously it was swallowed by ``**kwargs`` and the model silently fell through to the ``DEFAULT`` profile. Setting both at the same time to different values raises ``ValueError``. - ``service_endpoint=`` still wins when both endpoint and region are given. #260 — AgentConfig.name + Tool.func alias - ``AgentConfig.name: str | None`` is a real field that flows to ``Agent.name`` as a property. The previous ``extra='forbid'`` rejected ``AgentConfig(name=...)`` even though ``name`` is what users expect to set when labeling an agent in logs / multi-agent composers. - ``Tool.func`` is a ``@property`` alias for ``.fn``. Some downstream samples and the LangChain/LangGraph idiom reach for ``.func``; surfacing both names avoids the ``getattr(t, "fn", None) or getattr(t, "func", t)`` dance. Tests - Unit: AgentConfig.name + default, Tool.func is Tool.fn (sync + async), OCIModel region= builds the right URL, endpoint wins over region, profile= aliases profile_name, conflict raises, interrupt_before saves through the checkpointer, resume completes the graph past the gate. All 4885 unit tests pass. - Integration: new ``tests/integration/test_papercut_fixes_live.py`` exercises each fix end-to-end against a real OCI GenAI inference endpoint. Skips when OCI env vars aren't set. Verified locally against ``openai.gpt-5.5`` in ``us-chicago-1``. Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
…inline interrupt path The bundled three-papercut fix touched two save sites in ``StateGraph.execute()`` (the ``interrupt_before`` gate and the inline ``interrupt()`` branch). Initial coverage only exercised ``interrupt_before`` against ``MemoryCheckpointer``. Add tests so the save shape is verified end-to-end on: - ``FileCheckpointer`` (real JSON serialisation on disk) — proves ``AgentState.metadata`` round-trips through a non-memory backend that uses the canonical ``to_checkpoint()`` / ``from_checkpoint()`` pattern shared by every BaseCheckpointer implementation. - The inline ``interrupt()`` save site, against both Memory and File backends — this branch was broken on main (passed ``state=None``, crashed any backend calling ``state.to_checkpoint()``). The fix packs the graph state into ``AgentState.metadata`` and the new tests prove it persists correctly through both backends. Also re-ran ``tests/integration/test_checkpoint_backends.py`` and ``tests/integration/test_checkpointer_adapters.py``: 14 passed, 28 skipped (skipped require live Redis / PostgreSQL / OpenSearch / OCI Bucket services). No regressions on the lower-level save/load round trips. Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
…enSearch backends The fix at the ``interrupt_before`` and inline ``interrupt()`` save sites packs graph-level state into ``AgentState.metadata`` so it survives ``state.to_checkpoint()`` / ``state.from_checkpoint()``. Unit + file-backed coverage already verified the shape; these integration tests prove it round-trips through the two network-backed protocol backends that exercise real serialization paths: - ``redis_checkpointer`` — JSON serialization into Redis keys, then full reload from a separate Redis client call. - ``opensearch_checkpointer`` — JSON document indexing into OpenSearch, then ``_search`` round-trip via the OS REST API. Both tests pause→save→reload→assert metadata round-trips→resume→ assert the post-gate node ran. Skip cleanly when ``REDIS_URL`` / ``OPENSEARCH_HOSTS`` aren't set. Verified locally against a managed OCI OpenSearch dev cluster and the local Redis container shipped with the observai stack. Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
4 tasks
fede-kamel
added a commit
that referenced
this pull request
May 23, 2026
…gonomics + httpx 1.0 cap + trademark naming (#265) Four PRs of fixes since b20. No new public APIs; tightens the SDK on durability (StateGraph interrupt resume), ergonomics (OCIModel aliases, AgentConfig.name, Tool.func), deps (httpx<1.0 cap), and brings the docs site in line with the approved product name. - #261 — StateGraph.interrupt_before now writes through the checkpointer at the pause boundary; resume advances past the gate instead of re-pausing. Inline interrupt() save crash with state=None fixed in the same pass. OCIModel gains region= and profile= ergonomic aliases. AgentConfig.name + Tool.func surface the names users naturally reach for. - #262 — Capped httpx<1.0; pre-release 1.0.dev3 drops the top-level Auth re-export and broke OCIRequestSigner + BearerAuth at import. - #257 — Applied the Oracle Trademark Legal-approved full name (wordmark above hero H1, persistent header) and short name (body prose / OG meta / tab title) across docs, README, and contributor markdown. - #264 — OCI client read timeout default 60s→300s for reasoning models; integration fixture max_tokens 512→8192 so reasoning models have budget for both hidden chain-of-thought and visible output; eight stale integration tests refreshed against current catalogue / workbench layout. See CHANGELOG.md for the full breakdown. Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bundles the three papercut fixes filed as #258, #259, #260. Each is small enough that splitting them into separate PRs would be more churn than value.
#258 — StateGraph.interrupt_before now durable
execute(Command(resume=...))can recover the paused state across processes. The inlineinterrupt()path already saved;interrupt_beforedid not.interrupt_beforeand inlineinterrupt()) now pack the graph-level state intoAgentState.metadatainstead of passingstate=None. The previous shape crashed the in-protocol checkpointers that callstate.to_checkpoint()— same bug asinterrupt_before, fixed in one pass.Closes #258.
#259 — OCIModel region= and profile= aliases
region=builds the inference endpoint (https://inference.generativeai.<region>.oci.oraclecloud.com) whenservice_endpointis not provided. Lets you target a cross-region model without typing out the full URL.profile=is now an explicit alias forprofile_name=. Previously it was swallowed by**kwargsand the model silently fell through to theDEFAULTprofile. Setting both at once to different values raisesValueError.service_endpoint=still wins when both endpoint and region are given.Closes #259.
#260 — AgentConfig.name + Tool.func alias
AgentConfig.name: str | Noneis a real field; flows through to anameproperty onAgent. The previousextra='forbid'rejectedAgentConfig(name=...)even thoughnameis the obvious knob users reach for when labeling an agent in logs and multi-agent composers.Tool.funcis a@propertyalias for.fn. Some downstream samples and the LangChain/LangGraph idiom reach for.func; surfacing both names avoids thegetattr(t, "fn", None) or getattr(t, "func", t)dance.Closes #260.
Test plan
uv run pytest tests/unit/— 4885 unit tests passtest_agent_config.py,test_idempotent_tools.py,test_oci_model.py,test_graph.py)tests/integration/test_papercut_fixes_live.pyexercises each fix end-to-end against a real OCI GenAI inference endpoint, skipping when env vars aren't set. Verified locally againstopenai.gpt-5.5inus-chicago-1.pre-commit run --files <staged>— all hooks pass