Skip to content

fix(*): three papercuts — interrupt_before resume, OCIModel ergonomics, AgentConfig.name + Tool.func#261

Merged
fede-kamel merged 3 commits into
mainfrom
fix/three-papercuts-258-259-260
May 23, 2026
Merged

fix(*): three papercuts — interrupt_before resume, OCIModel ergonomics, AgentConfig.name + Tool.func#261
fede-kamel merged 3 commits into
mainfrom
fix/three-papercuts-258-259-260

Conversation

@fede-kamel
Copy link
Copy Markdown
Contributor

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

  • The pause boundary writes through the checkpointer, so a follow-up execute(Command(resume=...)) can recover the paused state across processes. The inline interrupt() path already saved; interrupt_before 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. The previous shape crashed the in-protocol checkpointers that call state.to_checkpoint() — same bug as interrupt_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) when service_endpoint is not provided. Lets you target 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 once to different values raises ValueError.
  • service_endpoint= still wins when both endpoint and region are given.

Closes #259.

#260 — AgentConfig.name + Tool.func alias

  • AgentConfig.name: str | None is a real field; flows through to a name property on Agent. The previous extra='forbid' rejected AgentConfig(name=...) even though name is the obvious knob users reach for when labeling an agent in logs and 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.

Closes #260.

Test plan

  • uv run pytest tests/unit/ — 4885 unit tests pass
  • New unit tests cover each fix (test_agent_config.py, test_idempotent_tools.py, test_oci_model.py, test_graph.py)
  • New integration suite tests/integration/test_papercut_fixes_live.py exercises each fix end-to-end against a real OCI GenAI inference endpoint, skipping when env vars aren't set. Verified locally against openai.gpt-5.5 in us-chicago-1.
  • pre-commit run --files <staged> — all hooks pass
  • CI green

…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>
@oracle-contributor-agreement oracle-contributor-agreement Bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label May 23, 2026
…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>
@fede-kamel fede-kamel merged commit ebbd213 into main May 23, 2026
10 checks passed
@fede-kamel fede-kamel deleted the fix/three-papercuts-258-259-260 branch May 23, 2026 14:33
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

1 participant