Skip to content

feat(adapters): add wrap_langgraph() 1-line wrapper (#1261)#122

Merged
saurabhjain1592 merged 8 commits intomainfrom
feat/1261-langgraph-wrapper
Mar 25, 2026
Merged

feat(adapters): add wrap_langgraph() 1-line wrapper (#1261)#122
saurabhjain1592 merged 8 commits intomainfrom
feat/1261-langgraph-wrapper

Conversation

@saurabhjain1592
Copy link
Copy Markdown
Member

Summary

  • wrap_langgraph() transparently wraps compiled LangGraph StateGraphs with AxonFlow governance — no changes to the graph definition
  • Uses langchain-core AsyncCallbackHandler to intercept node execution via metadata["langgraph_node"]
  • GovernedGraph exposes ainvoke() / invoke() / astream(), each creating a new workflow
  • NodeConfig for per-node step type/model/provider overrides
  • govern_tools=True enables automatic per-tool governance within nodes
  • Also adds 37 missing adapter tests for check_tool_gate(), tool_completed(), check_gate(), step_completed(), and context manager (#1278)

Test plan

  • 84 unit tests pass (52 adapter + 32 wrapper)
  • Adapter coverage: 76%, wrapper coverage: 87%
  • E2E: langgraph_wrapper_example.py passes against live Docker (10/10 assertions)
  • E2E: All existing examples still pass (no regressions)

…ernance (#1261)

Add transparent governance wrapper for compiled LangGraph StateGraphs.
Uses langchain-core AsyncCallbackHandler to intercept node execution
via metadata["langgraph_node"] without modifying the graph definition.

New public API:
- wrap_langgraph(graph, client=client, workflow_name=...) -> GovernedGraph
- GovernedGraph.ainvoke() / invoke() / astream()
- NodeConfig(step_type, model, provider, skip) per-node overrides
- govern_tools=True for automatic per-tool gate checks

Also adds 37 missing unit tests for check_tool_gate(), tool_completed(),
check_gate(), step_completed(), and context manager (#1278 gaps).

84 tests pass, adapter coverage 76%, wrapper coverage 87%.
@saurabhjain1592 saurabhjain1592 added the enhancement New feature or request label Mar 24, 2026
- Fix ruff lint: import ordering, EM101 string literal, TRY300 return
  in try, SIM108 ternary, UP035 AsyncIterator import, F401 unused
  StepType import
- Add ARG002 per-file-ignore for callback signatures (must match base)
- Restore monkeypatch for langchain-core import in tests (CI only
  installs [dev] extras, not [langgraph])
- Fix test lint: E501 line length, A002 builtin shadow, EM102 f-string
- Add type: ignore[import-not-found] for optional langchain_core import
- Add type: ignore[no-any-return] for dynamic import return
- Add type: ignore[valid-type] for dynamic base class
- Fix no-any-return in _detect_node_name with explicit str() and type annotation
- Add PLC0415, E501 to per-file-ignores for wrapper (lazy import pattern)
P1 fixes from code review:
- WorkflowApprovalRequiredError no longer aborts the workflow — leaves
  it in a resumable state so the caller can approve and retry
- Removed auto_block parameter from wrap_langgraph() and GovernedGraph —
  callbacks cannot return False to control graph flow, making
  auto_block=False unsafe (blocked nodes would still execute)
- Added test_approval_required_does_not_abort verifying abort_workflow
  is NOT called on approval-required responses
Users installing axonflow[all] expect all integrations to work.
langchain-core was only in [langgraph] extra, causing ImportError
when calling wrap_langgraph() after pip install axonflow[all].
@saurabhjain1592 saurabhjain1592 merged commit b21b5d2 into main Mar 25, 2026
12 checks passed
@saurabhjain1592 saurabhjain1592 deleted the feat/1261-langgraph-wrapper branch April 1, 2026 15:44
saurabhjain1592 added a commit that referenced this pull request Apr 17, 2026
Adds Python SDK half of ADR-043 + ADR-042.

New:
- axonflow.decisions module with DecisionExplanation, ExplainPolicy,
  ExplainRule Pydantic models. Shape frozen per ADR-043.
- AxonFlow.explain_decision(decision_id) async method calling
  GET /api/v1/decisions/:id/explain. Rejects empty decision_id with
  ValueError; relies on Pydantic validation for malformed responses.
- AuditSearchRequest gains three optional filters: decision_id,
  policy_name, override_id. Back-compat — old callers ignore them,
  new callers include them only when set.

Version: 6.3.0 -> 6.4.0. pyproject.toml + _version.py updated.

Tests (10 new, all passing):
- DecisionExplanation shape: minimum parse, full round-trip,
  forward-compat with unknown extra fields.
- ExplainPolicy/ExplainRule defaults.
- Client explain_decision: rejects empty id, happy path (monkeypatched
  orchestrator call with URL assertion), empty-response ValidationError.
- AuditSearchRequest: three new filters included when set, absent when
  unset (exclude_none behavior).

Companion to platform v7.1.0 (axonflow-enterprise PR #1605) and Go SDK
v5.4.0 (axonflow-sdk-go PR #122).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant