openbox-langgraph-sdk-python 0.2.0__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.coverage +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.github/workflows/pr-quality.yml +1 -1
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.github/workflows/publish.yml +1 -1
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.gitignore +4 -1
- openbox_langgraph_sdk_python-1.1.0/CHANGELOG.md +77 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/CLAUDE.md +4 -2
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/PKG-INFO +58 -13
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/README.md +53 -10
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/coverage.xml +1709 -1216
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/.env.example +16 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/.gitignore +5 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/AGENTS.md +43 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/README.md +68 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/pyproject.toml +31 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/skills/blog-post/SKILL.md +126 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/skills/social-media/SKILL.md +177 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/__init__.py +1 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/agent.py +74 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/main.py +101 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/paths.py +10 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/prompt.py +77 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/tools_content.py +84 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/tools_fs.py +63 -0
- openbox_langgraph_sdk_python-1.1.0/demo/demo_04_content_builder_langgraph/uv.lock +2143 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/__init__.py +5 -0
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/activity_context_binding.py +126 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/client.py +259 -51
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/config.py +86 -1
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/core_adapter.py +228 -0
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/core_events.py +141 -0
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/core_runtime.py +175 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/errors.py +30 -1
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/identity.py +51 -27
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/langgraph_handler.py +839 -301
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/langgraph_hook_runtime.py +210 -0
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/otel_setup.py +36 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/span_processor.py +18 -6
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/tool_activity_binding.py +339 -0
- openbox_langgraph_sdk_python-1.1.0/openbox_langgraph/trace_context_registry.py +197 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/tracing.py +7 -127
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/types.py +168 -9
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/pyproject.toml +19 -2
- openbox_langgraph_sdk_python-1.1.0/tests/conftest.py +69 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/README.md +171 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/__init__.py +6 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/capture_harness.py +177 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/chain_completed.normalized.json +60 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/chain_completed.raw.json +60 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/chain_started.handbuilt_serialization_pin.normalized.json +17 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/chain_started.handbuilt_serialization_pin.raw.json +17 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/fake_agent_graphs.py +125 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/generate_fixtures.py +135 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/graph_capture_harness.py +196 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/headers_signed.normalized.json +34 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/headers_signed.raw.json +34 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/headers_unsigned.normalized.json +24 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/headers_unsigned.raw.json +24 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/id_normalization.py +135 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/layer1_handbuilt_pins.py +71 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/llm_completed.normalized.json +29 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/llm_completed.raw.json +29 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/llm_started.normalized.json +18 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/llm_started.raw.json +18 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/ordering_single_llm_turn.json +22 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/ordering_tool_call_turn.json +38 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/ordering_two_llm_calls_turn.json +30 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/real_emitted_event_fixtures.py +136 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/signal_received.normalized.json +16 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/signal_received.raw.json +16 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/subagent_tool_completed.normalized.json +30 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/subagent_tool_completed.raw.json +30 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/subagent_tool_started.normalized.json +31 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/subagent_tool_started.raw.json +31 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/tool_completed.normalized.json +28 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/tool_completed.raw.json +28 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/tool_started.normalized.json +23 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/tool_started.raw.json +23 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/workflow_completed_error_close.normalized.json +14 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/workflow_completed_error_close.raw.json +14 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/workflow_failed.handbuilt_serialization_pin.normalized.json +16 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/workflow_failed.handbuilt_serialization_pin.raw.json +16 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/workflow_started.normalized.json +26 -0
- openbox_langgraph_sdk_python-1.1.0/tests/golden/workflow_started.raw.json +26 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_activity_context_binding.py +688 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_approval_strict_parsing.py +76 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_client_shim_compat.py +99 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/tests/test_config_client_core.py +4 -2
- openbox_langgraph_sdk_python-1.1.0/tests/test_config_resolution_precedence.py +29 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_context_cleanup_on_error.py +341 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_context_fallback_task_and_thread.py +194 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_context_turn_isolation.py +315 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_core_conformance_suite.py +173 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_core_context_binding.py +361 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_core_events_envelopes.py +299 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_core_runtime_config.py +126 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/tests/test_did_client_signing.py +0 -43
- openbox_langgraph_sdk_python-1.1.0/tests/test_fail_open_block_preserved.py +113 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_framework_adapter_translation.py +247 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_gate_error_translation.py +136 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_golden_baseline.py +214 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_governance_changes.py +158 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_halt_run_isolation.py +157 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_hook_approval_retry.py +242 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_hook_context_pinning.py +128 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_hook_family_exclusivity.py +207 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_langchain_callback_dedup.py +522 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_langchain_callback_llm_context.py +531 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_langchain_callback_tool_ordering.py +391 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_lifecycle_golden_parity.py +158 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_loop_liveness_on_sync_approval.py +131 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_public_exports_baseline.py +116 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_recording_client_seam.py +64 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_signed_headers_parity.py +74 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_types_hook_core.py +98 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_version_static.py +53 -0
- openbox_langgraph_sdk_python-1.1.0/tests/test_workload_identity.py +500 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/uv.lock +241 -117
- openbox_langgraph_sdk_python-0.2.0/openbox_langgraph/db_governance_hooks.py +0 -897
- openbox_langgraph_sdk_python-0.2.0/openbox_langgraph/file_governance_hooks.py +0 -419
- openbox_langgraph_sdk_python-0.2.0/openbox_langgraph/hook_governance.py +0 -424
- openbox_langgraph_sdk_python-0.2.0/openbox_langgraph/http_governance_hooks.py +0 -723
- openbox_langgraph_sdk_python-0.2.0/openbox_langgraph/otel_setup.py +0 -477
- openbox_langgraph_sdk_python-0.2.0/plans/260320-0329-remove-span-collector/plan.md +0 -121
- openbox_langgraph_sdk_python-0.2.0/plans/260321-2019-port-deepagent-fixes/phase-01-remove-hitl-gates.md +0 -53
- openbox_langgraph_sdk_python-0.2.0/plans/260321-2019-port-deepagent-fixes/phase-02-sqlalchemy-engine.md +0 -46
- openbox_langgraph_sdk_python-0.2.0/plans/260321-2019-port-deepagent-fixes/phase-03-hook-hitl-retry.md +0 -80
- openbox_langgraph_sdk_python-0.2.0/plans/260321-2019-port-deepagent-fixes/plan.md +0 -42
- openbox_langgraph_sdk_python-0.2.0/plans/reports/Explore-260330-1430-comprehensive-sdk-analysis.md +0 -1753
- openbox_langgraph_sdk_python-0.2.0/plans/reports/Explore-260330-2300-file-reference.md +0 -215
- openbox_langgraph_sdk_python-0.2.0/plans/reports/Explore-260330-2300-integration-guide.md +0 -747
- openbox_langgraph_sdk_python-0.2.0/plans/reports/code-reviewer-260323-1101-code-reuse-otel-hooks.md +0 -206
- openbox_langgraph_sdk_python-0.2.0/plans/reports/code-reviewer-260323-1101-efficiency-review-otel-http-hook-spans.md +0 -193
- openbox_langgraph_sdk_python-0.2.0/plans/reports/code-reviewer-260323-1101-hacky-patterns-review.md +0 -175
- openbox_langgraph_sdk_python-0.2.0/plans/reports/docs-manager-260321-2153-initial-documentation.md +0 -363
- openbox_langgraph_sdk_python-0.2.0/plans/reports/span-flow-visualization.html +0 -456
- openbox_langgraph_sdk_python-0.2.0/tests/test_governance_changes.py +0 -279
- openbox_langgraph_sdk_python-0.2.0/tests/test_telemetry_payload.py +0 -333
- openbox_langgraph_sdk_python-0.2.0/tests/test_types_hook_core.py +0 -214
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.github/CODEOWNERS +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.github/workflows/pr-governance.yml +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.github/workflows/pr-security.yml +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/.gitleaks.toml +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/AGENTS.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/CODE_OF_CONDUCT.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/LICENSE +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/SECURITY.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/docs/code-standards.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/docs/codebase-summary.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/docs/project-overview-pdr.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/docs/project-roadmap.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/docs/system-architecture.md +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/hitl.py +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/openbox_langgraph/verdict_handler.py +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/sonar-project.properties +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/tests/test_agent_identity.py +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/tests/test_contextvars_propagation.py +0 -0
- {openbox_langgraph_sdk_python-0.2.0 → openbox_langgraph_sdk_python-1.1.0}/tests/test_verdict_span_hitl_core.py +0 -0
|
Binary file
|
|
@@ -165,7 +165,7 @@ jobs:
|
|
|
165
165
|
id: sonarqube_quality_gate
|
|
166
166
|
if: ${{ env.SONAR_TOKEN != '' && env.SONAR_HOST_URL != '' }}
|
|
167
167
|
continue-on-error: true
|
|
168
|
-
uses: SonarSource/sonarqube-quality-gate-action@
|
|
168
|
+
uses: SonarSource/sonarqube-quality-gate-action@v1.2.0
|
|
169
169
|
with:
|
|
170
170
|
pollingTimeoutSec: 600
|
|
171
171
|
env:
|
|
@@ -342,7 +342,7 @@ jobs:
|
|
|
342
342
|
id: sonarqube_quality_gate
|
|
343
343
|
if: ${{ env.SONAR_TOKEN != '' && env.SONAR_HOST_URL != '' }}
|
|
344
344
|
continue-on-error: true
|
|
345
|
-
uses: SonarSource/sonarqube-quality-gate-action@
|
|
345
|
+
uses: SonarSource/sonarqube-quality-gate-action@v1.2.0
|
|
346
346
|
with:
|
|
347
347
|
pollingTimeoutSec: 600
|
|
348
348
|
env:
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
- Upgrade `openbox-sdk-python` to `>=1.4.0` for IAM v3 workload identity. Keep
|
|
6
|
+
`openbox-langchain-sdk-python` at `>=1.0.0` (locked to 1.0.0).
|
|
7
|
+
- Update locked AnyIO to 4.14.2 and urllib3 to 2.8.0 in the SDK and demo, plus
|
|
8
|
+
pyasn1 to 0.6.4 in the demo, to address Trivy's critical/high findings.
|
|
9
|
+
- Add `workload_private_key` to initialization, graph creation, runtime creation,
|
|
10
|
+
and standalone governance clients, with framework/global environment support
|
|
11
|
+
during initialization and runtime creation.
|
|
12
|
+
- Delegate workload bootstrap, token exchange, caching, and refresh to the base
|
|
13
|
+
SDK. Reuse the handler's runtime client for validation, sync/raw evaluation,
|
|
14
|
+
and approval polling alongside callbacks and operation hooks.
|
|
15
|
+
- Preserve authentication, signing, and bootstrap/configuration errors under
|
|
16
|
+
fail-open policies. Export `OpenBoxSigningError` with Core's `reason_code`.
|
|
17
|
+
- Preserve legacy DID/API-key configuration and the base SDK's explicit
|
|
18
|
+
no-workload-authority fallback for rolling upgrades.
|
|
19
|
+
|
|
20
|
+
## 0.3.0
|
|
21
|
+
|
|
22
|
+
Migrates the SDK onto the shared `openbox-sdk-python` (`openbox_core`) governance
|
|
23
|
+
core. The public API (classes, functions, `initialize()` signature, DID signing)
|
|
24
|
+
is preserved; the changes below are internal rewiring plus a small, deliberate
|
|
25
|
+
set of wire and semantic changes, each regression-gated by a reproducible
|
|
26
|
+
golden-payload oracle.
|
|
27
|
+
|
|
28
|
+
### Changed — wire protocol (lifecycle events)
|
|
29
|
+
|
|
30
|
+
- Lifecycle events (`SignalReceived`, `WorkflowStarted`/`Completed`,
|
|
31
|
+
`LLMStarted`/`Completed`, `ToolStarted`/`Completed`) now serialize through the
|
|
32
|
+
shared `openbox_core` `EventEnvelope` + strict gate instead of hand-built
|
|
33
|
+
request bodies. The wire body is byte-identical to before **except** three
|
|
34
|
+
compatibility-noise fields the base envelope omits by construction and no
|
|
35
|
+
longer sends for lifecycle events: `hook_trigger: false`, `spans: []`,
|
|
36
|
+
`span_count: 0`. Core treats an absent `hook_trigger` as `false`; this is the
|
|
37
|
+
same envelope format the Temporal SDK already ships to Core.
|
|
38
|
+
- Lifecycle-event requests now carry the base SDK's `User-Agent`; hook-triggered
|
|
39
|
+
requests keep `OpenBox-LangGraph-SDK/<version>`.
|
|
40
|
+
|
|
41
|
+
### Changed — semantics
|
|
42
|
+
|
|
43
|
+
- **Approval parsing is action-first and strict.** When both are present the
|
|
44
|
+
`action` field now wins over `verdict` (was verdict-first). An unknown or
|
|
45
|
+
empty approval response resolves to *pending* (keeps polling) — never an
|
|
46
|
+
implicit approve. The previous lenient "unknown → allow" fallback at the
|
|
47
|
+
human-approval boundary is removed.
|
|
48
|
+
- **Hook-level HITL approval retry now runs governed.** After an approval is
|
|
49
|
+
granted, the pending abort state is cleared on both the base and legacy stores
|
|
50
|
+
before the graph re-invokes. Previously the stale abort flag re-blocked the
|
|
51
|
+
approved retry (`clear_activity_abort` had no caller) — a genuine bug, now
|
|
52
|
+
fixed.
|
|
53
|
+
- **Fail-open is precise.** A governance transport/parse failure surfaces as
|
|
54
|
+
"no verdict" (fail-open, unchanged) only for a genuine client-synthesized
|
|
55
|
+
fallback; a real blocking verdict that happens to carry `fallback_used: true`
|
|
56
|
+
still enforces.
|
|
57
|
+
- Expired-approval-before-allow ordering is unchanged (an expired approval
|
|
58
|
+
raises even when allow-shaped).
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
|
|
62
|
+
- **`use_core_instrumentation`** config flag (default `False`). When enabled,
|
|
63
|
+
covered hook families (`http`, `dbapi`, `asyncpg`, `sqlalchemy`, `file`) are
|
|
64
|
+
governed through the shared `openbox_core` hook runtime while uncovered
|
|
65
|
+
families (`urllib`, `urllib3`, `redis`, `mongo`) stay on the legacy hooks —
|
|
66
|
+
each operation governed exactly once. Approval on this path is raise-only and
|
|
67
|
+
never blocks the event loop. Per-family flips (making the core runtime the
|
|
68
|
+
default for a family) remain follow-up work.
|
|
69
|
+
- `openbox_langgraph.__version__`.
|
|
70
|
+
- `multi_agent_session_id` config/handler option (distinct from `session_id`).
|
|
71
|
+
- Dependency on `openbox-sdk-python` (the shared governance core).
|
|
72
|
+
|
|
73
|
+
### Preserved (regression-gated)
|
|
74
|
+
|
|
75
|
+
DID request signing (byte-identical `X-OpenBox-Agent-*` headers), the
|
|
76
|
+
`(activity_id, event_type)` de-dup, transient-failure PII redaction, the
|
|
77
|
+
public `client=` injection seam, and every public class/function signature.
|
|
@@ -37,8 +37,10 @@ cd test-agent && uv run python agent.py
|
|
|
37
37
|
|
|
38
38
|
The SDK has three governance layers that intercept operations at different levels:
|
|
39
39
|
|
|
40
|
-
### Layer 1:
|
|
41
|
-
|
|
40
|
+
### Layer 1: Tool/LLM Lifecycle (Producer-Owned via LangChain-Core Callback)
|
|
41
|
+
Tool and LLM lifecycle emission is **owned by the callback layer** (`openbox-langchain-sdk-python`). The `OpenBoxLangChainCoreAsyncCallbackHandler` / `...SyncCallbackHandler` emit lifecycle events (ActivityStarted, ActivityCompleted, LLMStarted, LLMCompleted) directly to OpenBox Core via the `ActivityBridge` ownership channel. This fixes span ordering/correlation bugs: tool hook spans now nest inside the tool's ActivityStarted activity; LLM provider hook spans map into the LLM activity; completions reuse the start activity_id (no more `-c` suffix).
|
|
42
|
+
|
|
43
|
+
The LangGraph stream-event layer serves as a **fallback for telemetry and span reconstruction** when the callback is not installed (e.g., injected clients or subagent-gated handlers). Completions use stream events for telemetry only — `gate.aevaluate()` polls and continues, never retries the graph. **Sync agents fail-shut on REQUIRE_APPROVAL** (no working sync approval poller).
|
|
42
44
|
|
|
43
45
|
### Layer 2: Hook Governance (http/db/file_governance_hooks.py)
|
|
44
46
|
Intercepts low-level operations using built-in instrumentation:
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: openbox-langgraph-sdk-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: OpenBox governance and observability SDK for LangGraph
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.11
|
|
8
|
-
Requires-Dist: cryptography>=42.0.0
|
|
9
8
|
Requires-Dist: httpx>=0.27.0
|
|
10
9
|
Requires-Dist: langchain-core>=1.3.3
|
|
11
10
|
Requires-Dist: langgraph>=0.2.0
|
|
11
|
+
Requires-Dist: langsmith>=0.8.18
|
|
12
|
+
Requires-Dist: openbox-langchain-sdk-python>=1.0.0
|
|
13
|
+
Requires-Dist: openbox-sdk-python>=1.4.0
|
|
12
14
|
Requires-Dist: opentelemetry-api>=1.20.0
|
|
13
15
|
Requires-Dist: opentelemetry-instrumentation-asyncpg>=0.41b0
|
|
14
16
|
Requires-Dist: opentelemetry-instrumentation-httpx>=0.41b0
|
|
@@ -84,10 +86,11 @@ Your code SDK (3 layers) OpenBox Co
|
|
|
84
86
|
|
|
85
87
|
governed.ainvoke()
|
|
86
88
|
│
|
|
87
|
-
├─ Layer 1:
|
|
88
|
-
│
|
|
89
|
-
│
|
|
90
|
-
│
|
|
89
|
+
├─ Layer 1: Tool/LLM Lifecycle (openbox-langchain-sdk-python)
|
|
90
|
+
│ Tool lifecycle via LangChain-Core callback ────────────────→ Policy engine
|
|
91
|
+
│ LLM lifecycle via LangChain-Core callback ───────────────→ Guardrails
|
|
92
|
+
│ ActivityBridge deduplicates callback events
|
|
93
|
+
│ Stream events serve as fallback (when callback not installed)
|
|
91
94
|
│ ↑ enforce verdict (allow / block / redact / pause)
|
|
92
95
|
│
|
|
93
96
|
├─ Layer 2: Hook Governance (http/db/file hooks)
|
|
@@ -101,7 +104,7 @@ governed.ainvoke()
|
|
|
101
104
|
Links hook-level operations to the tool call that triggered them
|
|
102
105
|
```
|
|
103
106
|
|
|
104
|
-
**Layer 1**
|
|
107
|
+
**Layer 1** tool and LLM lifecycle is **producer-owned** via the LangChain-Core callback (owned by `openbox-langchain-sdk-python`). It sends governance events (ActivityStarted, LLMStarted, etc.) to OpenBox Core and enforces verdicts. The LangGraph event stream serves as a fallback when the callback is not installed (e.g., injected clients or subagent-gated handlers); completions use stream events for telemetry only via `gate.aevaluate` (poll-and-continue, never retry-the-graph).
|
|
105
108
|
|
|
106
109
|
**Layer 2** uses built-in instrumentation to intercept low-level operations (HTTP requests, DB queries, file I/O) made by your tools. Each operation is evaluated at two stages: `started` (can block) and `completed` (informational).
|
|
107
110
|
|
|
@@ -133,17 +136,14 @@ uv add openbox-langgraph-sdk-python
|
|
|
133
136
|
|
|
134
137
|
### 1. Get your agent credentials
|
|
135
138
|
|
|
136
|
-
Sign in to [dashboard.openbox.ai](https://dashboard.openbox.ai), create an agent called `"MyAgent"`, and copy
|
|
137
|
-
|
|
138
|
-
New OpenBox agents have DID signing enabled by default. Keep the private key secret and load it from your environment.
|
|
139
|
+
Sign in to [dashboard.openbox.ai](https://dashboard.openbox.ai), create an agent called `"MyAgent"`, and copy its API key. For an IAM v3 workload-enabled agent, also load the PKCS8 PEM RSA private key registered for its active Keycloak service account. Keep the key secret.
|
|
139
140
|
|
|
140
141
|
### 2. Set environment variables
|
|
141
142
|
|
|
142
143
|
```bash
|
|
143
144
|
export OPENBOX_URL="https://core.openbox.ai"
|
|
144
145
|
export OPENBOX_API_KEY="obx_live_..."
|
|
145
|
-
export
|
|
146
|
-
export OPENBOX_AGENT_PRIVATE_KEY="..."
|
|
146
|
+
export OPENBOX_WORKLOAD_PRIVATE_KEY="$(cat /path/to/workload-private-key.pem)"
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
### 3. Wrap your graph
|
|
@@ -178,6 +178,50 @@ asyncio.run(main())
|
|
|
178
178
|
|
|
179
179
|
That's it. Your agent now sends governance events to OpenBox on every tool call, LLM prompt, HTTP request, and database query.
|
|
180
180
|
|
|
181
|
+
### IAM v3 workload identity
|
|
182
|
+
|
|
183
|
+
IAM v3 is provided by `openbox-sdk-python>=1.4.0`. The existing
|
|
184
|
+
`openbox-langchain-sdk-python` dependency remains at `>=1.0.0`; its callbacks
|
|
185
|
+
use the same base runtime as the LangGraph handler and operation hooks.
|
|
186
|
+
|
|
187
|
+
You can pass the workload key explicitly instead of setting an environment variable:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
governed = create_openbox_graph_handler(
|
|
191
|
+
graph=agent,
|
|
192
|
+
api_url=os.environ["OPENBOX_URL"],
|
|
193
|
+
api_key=os.environ["OPENBOX_API_KEY"],
|
|
194
|
+
workload_private_key=os.environ["OPENBOX_WORKLOAD_PRIVATE_KEY"],
|
|
195
|
+
)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Key resolution is explicit argument, then `OPENBOX_LANGGRAPH_WORKLOAD_PRIVATE_KEY`,
|
|
199
|
+
then `OPENBOX_WORKLOAD_PRIVATE_KEY`. The value is the PEM contents, not a file path.
|
|
200
|
+
The Python base SDK selects workload authentication from this key; no
|
|
201
|
+
`OPENBOX_AGENT_IDENTITY_METHOD` setting is needed for IAM v3.
|
|
202
|
+
|
|
203
|
+
The base SDK fetches `/api/v3/auth/bootstrap`, exchanges a signed `private_key_jwt`
|
|
204
|
+
for a short-lived Keycloak token, and sends the API key plus
|
|
205
|
+
`X-OpenBox-Workload-Token` on v3 validation, evaluation, and approval requests.
|
|
206
|
+
It owns token caching and refresh for OpenBox-, Okta-, and Entra-managed identities.
|
|
207
|
+
Lifecycle callbacks, hooks, synchronous/raw evaluations, and approval polling share
|
|
208
|
+
the handler's runtime client. A standalone `GovernanceClient` also accepts
|
|
209
|
+
`workload_private_key`; call `await client.close()` when finished with it.
|
|
210
|
+
|
|
211
|
+
Authentication and signing failures raise `OpenBoxAuthError` or its subclass
|
|
212
|
+
`OpenBoxSigningError` even with `on_api_error="fail_open"`. The signing error retains
|
|
213
|
+
Core's `reason_code`. Invalid bootstrap metadata raises `OpenBoxConfigError`, and
|
|
214
|
+
bootstrap/token service outages raise `OpenBoxNetworkError`; these do not become
|
|
215
|
+
implicit ALLOW or pending approval results. `validate=False` skips the startup
|
|
216
|
+
network check only: the key is still validated locally, and runtime requests
|
|
217
|
+
still authenticate.
|
|
218
|
+
|
|
219
|
+
The base SDK preserves rolling-upgrade compatibility: bootstrap HTTP 404, or
|
|
220
|
+
HTTP 409 with `workload_identity_unavailable`, retains the configured legacy route.
|
|
221
|
+
Other bootstrap failures do not downgrade. Existing DID signing remains available
|
|
222
|
+
through `agent_did`/`agent_private_key` or `OPENBOX_AGENT_DID`/`OPENBOX_AGENT_PRIVATE_KEY`.
|
|
223
|
+
Without identity credentials, the existing API-key-only behavior is preserved.
|
|
224
|
+
|
|
181
225
|
### Try it locally (included test agent)
|
|
182
226
|
|
|
183
227
|
The repository includes a runnable LangGraph test agent under `test-agent/`.
|
|
@@ -204,6 +248,7 @@ See `test-agent/README.md` for setup and run instructions.
|
|
|
204
248
|
| `api_key` | `str` | **required** | API key (`obx_live_*` or `obx_test_*`) |
|
|
205
249
|
| `agent_did` | `str` | `OPENBOX_AGENT_DID` | Agent DID used to sign governance requests |
|
|
206
250
|
| `agent_private_key` | `str` | `OPENBOX_AGENT_PRIVATE_KEY` | Base64 raw Ed25519 private key seed for the agent DID |
|
|
251
|
+
| `workload_private_key` | `str` | `OPENBOX_LANGGRAPH_WORKLOAD_PRIVATE_KEY`, then `OPENBOX_WORKLOAD_PRIVATE_KEY` | PKCS8 PEM RSA key for IAM v3 workload authentication |
|
|
207
252
|
| `agent_name` | `str` | `None` | Agent name as configured in the dashboard |
|
|
208
253
|
| `validate` | `bool` | `True` | Validate API key against server on startup |
|
|
209
254
|
| `on_api_error` | `str` | `"fail_open"` | `"fail_open"` (allow on error) or `"fail_closed"` (block on error) |
|
|
@@ -44,10 +44,11 @@ Your code SDK (3 layers) OpenBox Co
|
|
|
44
44
|
|
|
45
45
|
governed.ainvoke()
|
|
46
46
|
│
|
|
47
|
-
├─ Layer 1:
|
|
48
|
-
│
|
|
49
|
-
│
|
|
50
|
-
│
|
|
47
|
+
├─ Layer 1: Tool/LLM Lifecycle (openbox-langchain-sdk-python)
|
|
48
|
+
│ Tool lifecycle via LangChain-Core callback ────────────────→ Policy engine
|
|
49
|
+
│ LLM lifecycle via LangChain-Core callback ───────────────→ Guardrails
|
|
50
|
+
│ ActivityBridge deduplicates callback events
|
|
51
|
+
│ Stream events serve as fallback (when callback not installed)
|
|
51
52
|
│ ↑ enforce verdict (allow / block / redact / pause)
|
|
52
53
|
│
|
|
53
54
|
├─ Layer 2: Hook Governance (http/db/file hooks)
|
|
@@ -61,7 +62,7 @@ governed.ainvoke()
|
|
|
61
62
|
Links hook-level operations to the tool call that triggered them
|
|
62
63
|
```
|
|
63
64
|
|
|
64
|
-
**Layer 1**
|
|
65
|
+
**Layer 1** tool and LLM lifecycle is **producer-owned** via the LangChain-Core callback (owned by `openbox-langchain-sdk-python`). It sends governance events (ActivityStarted, LLMStarted, etc.) to OpenBox Core and enforces verdicts. The LangGraph event stream serves as a fallback when the callback is not installed (e.g., injected clients or subagent-gated handlers); completions use stream events for telemetry only via `gate.aevaluate` (poll-and-continue, never retry-the-graph).
|
|
65
66
|
|
|
66
67
|
**Layer 2** uses built-in instrumentation to intercept low-level operations (HTTP requests, DB queries, file I/O) made by your tools. Each operation is evaluated at two stages: `started` (can block) and `completed` (informational).
|
|
67
68
|
|
|
@@ -93,17 +94,14 @@ uv add openbox-langgraph-sdk-python
|
|
|
93
94
|
|
|
94
95
|
### 1. Get your agent credentials
|
|
95
96
|
|
|
96
|
-
Sign in to [dashboard.openbox.ai](https://dashboard.openbox.ai), create an agent called `"MyAgent"`, and copy
|
|
97
|
-
|
|
98
|
-
New OpenBox agents have DID signing enabled by default. Keep the private key secret and load it from your environment.
|
|
97
|
+
Sign in to [dashboard.openbox.ai](https://dashboard.openbox.ai), create an agent called `"MyAgent"`, and copy its API key. For an IAM v3 workload-enabled agent, also load the PKCS8 PEM RSA private key registered for its active Keycloak service account. Keep the key secret.
|
|
99
98
|
|
|
100
99
|
### 2. Set environment variables
|
|
101
100
|
|
|
102
101
|
```bash
|
|
103
102
|
export OPENBOX_URL="https://core.openbox.ai"
|
|
104
103
|
export OPENBOX_API_KEY="obx_live_..."
|
|
105
|
-
export
|
|
106
|
-
export OPENBOX_AGENT_PRIVATE_KEY="..."
|
|
104
|
+
export OPENBOX_WORKLOAD_PRIVATE_KEY="$(cat /path/to/workload-private-key.pem)"
|
|
107
105
|
```
|
|
108
106
|
|
|
109
107
|
### 3. Wrap your graph
|
|
@@ -138,6 +136,50 @@ asyncio.run(main())
|
|
|
138
136
|
|
|
139
137
|
That's it. Your agent now sends governance events to OpenBox on every tool call, LLM prompt, HTTP request, and database query.
|
|
140
138
|
|
|
139
|
+
### IAM v3 workload identity
|
|
140
|
+
|
|
141
|
+
IAM v3 is provided by `openbox-sdk-python>=1.4.0`. The existing
|
|
142
|
+
`openbox-langchain-sdk-python` dependency remains at `>=1.0.0`; its callbacks
|
|
143
|
+
use the same base runtime as the LangGraph handler and operation hooks.
|
|
144
|
+
|
|
145
|
+
You can pass the workload key explicitly instead of setting an environment variable:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
governed = create_openbox_graph_handler(
|
|
149
|
+
graph=agent,
|
|
150
|
+
api_url=os.environ["OPENBOX_URL"],
|
|
151
|
+
api_key=os.environ["OPENBOX_API_KEY"],
|
|
152
|
+
workload_private_key=os.environ["OPENBOX_WORKLOAD_PRIVATE_KEY"],
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Key resolution is explicit argument, then `OPENBOX_LANGGRAPH_WORKLOAD_PRIVATE_KEY`,
|
|
157
|
+
then `OPENBOX_WORKLOAD_PRIVATE_KEY`. The value is the PEM contents, not a file path.
|
|
158
|
+
The Python base SDK selects workload authentication from this key; no
|
|
159
|
+
`OPENBOX_AGENT_IDENTITY_METHOD` setting is needed for IAM v3.
|
|
160
|
+
|
|
161
|
+
The base SDK fetches `/api/v3/auth/bootstrap`, exchanges a signed `private_key_jwt`
|
|
162
|
+
for a short-lived Keycloak token, and sends the API key plus
|
|
163
|
+
`X-OpenBox-Workload-Token` on v3 validation, evaluation, and approval requests.
|
|
164
|
+
It owns token caching and refresh for OpenBox-, Okta-, and Entra-managed identities.
|
|
165
|
+
Lifecycle callbacks, hooks, synchronous/raw evaluations, and approval polling share
|
|
166
|
+
the handler's runtime client. A standalone `GovernanceClient` also accepts
|
|
167
|
+
`workload_private_key`; call `await client.close()` when finished with it.
|
|
168
|
+
|
|
169
|
+
Authentication and signing failures raise `OpenBoxAuthError` or its subclass
|
|
170
|
+
`OpenBoxSigningError` even with `on_api_error="fail_open"`. The signing error retains
|
|
171
|
+
Core's `reason_code`. Invalid bootstrap metadata raises `OpenBoxConfigError`, and
|
|
172
|
+
bootstrap/token service outages raise `OpenBoxNetworkError`; these do not become
|
|
173
|
+
implicit ALLOW or pending approval results. `validate=False` skips the startup
|
|
174
|
+
network check only: the key is still validated locally, and runtime requests
|
|
175
|
+
still authenticate.
|
|
176
|
+
|
|
177
|
+
The base SDK preserves rolling-upgrade compatibility: bootstrap HTTP 404, or
|
|
178
|
+
HTTP 409 with `workload_identity_unavailable`, retains the configured legacy route.
|
|
179
|
+
Other bootstrap failures do not downgrade. Existing DID signing remains available
|
|
180
|
+
through `agent_did`/`agent_private_key` or `OPENBOX_AGENT_DID`/`OPENBOX_AGENT_PRIVATE_KEY`.
|
|
181
|
+
Without identity credentials, the existing API-key-only behavior is preserved.
|
|
182
|
+
|
|
141
183
|
### Try it locally (included test agent)
|
|
142
184
|
|
|
143
185
|
The repository includes a runnable LangGraph test agent under `test-agent/`.
|
|
@@ -164,6 +206,7 @@ See `test-agent/README.md` for setup and run instructions.
|
|
|
164
206
|
| `api_key` | `str` | **required** | API key (`obx_live_*` or `obx_test_*`) |
|
|
165
207
|
| `agent_did` | `str` | `OPENBOX_AGENT_DID` | Agent DID used to sign governance requests |
|
|
166
208
|
| `agent_private_key` | `str` | `OPENBOX_AGENT_PRIVATE_KEY` | Base64 raw Ed25519 private key seed for the agent DID |
|
|
209
|
+
| `workload_private_key` | `str` | `OPENBOX_LANGGRAPH_WORKLOAD_PRIVATE_KEY`, then `OPENBOX_WORKLOAD_PRIVATE_KEY` | PKCS8 PEM RSA key for IAM v3 workload authentication |
|
|
167
210
|
| `agent_name` | `str` | `None` | Agent name as configured in the dashboard |
|
|
168
211
|
| `validate` | `bool` | `True` | Validate API key against server on startup |
|
|
169
212
|
| `on_api_error` | `str` | `"fail_open"` | `"fail_open"` (allow on error) or `"fail_closed"` (block on error) |
|