openbox-langgraph-sdk-python 1.0.0__tar.gz → 1.2.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-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.coverage +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/pr-quality.yml +1 -1
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/publish.yml +1 -1
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/CHANGELOG.md +26 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/PKG-INFO +61 -9
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/README.md +58 -6
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/coverage.xml +1100 -894
- openbox_langgraph_sdk_python-1.2.0/demo/demo_04_content_builder_langgraph/.env.example +16 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/uv.lock +75 -62
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/__init__.py +3 -1
- openbox_langgraph_sdk_python-1.2.0/openbox_langgraph/activity_approval.py +156 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/client.py +105 -20
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/config.py +55 -1
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/core_adapter.py +34 -77
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/core_runtime.py +7 -1
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/errors.py +30 -1
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/identity.py +14 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/langgraph_handler.py +34 -147
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/langgraph_hook_runtime.py +9 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/pyproject.toml +2 -2
- openbox_langgraph_sdk_python-1.2.0/tests/test_activity_approval_waiter.py +98 -0
- openbox_langgraph_sdk_python-1.2.0/tests/test_approval_in_place.py +196 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_context_cleanup_on_error.py +13 -20
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_context_binding.py +12 -1
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_framework_adapter_translation.py +14 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_gate_error_translation.py +35 -3
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_hook_approval_retry.py +27 -83
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_langchain_callback_tool_ordering.py +20 -46
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_public_exports_baseline.py +3 -2
- openbox_langgraph_sdk_python-1.2.0/tests/test_workload_identity.py +500 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/uv.lock +72 -59
- openbox_langgraph_sdk_python-1.0.0/demo/demo_04_content_builder_langgraph/.env.example +0 -11
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/CODEOWNERS +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/pr-governance.yml +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/pr-security.yml +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.gitignore +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.gitleaks.toml +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/AGENTS.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/CLAUDE.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/CODE_OF_CONDUCT.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/LICENSE +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/SECURITY.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/.gitignore +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/AGENTS.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/README.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/pyproject.toml +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/skills/blog-post/SKILL.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/skills/social-media/SKILL.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/__init__.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/agent.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/main.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/paths.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/prompt.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/tools_content.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/src/demo_04_content_builder_langgraph/tools_fs.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/code-standards.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/codebase-summary.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/project-overview-pdr.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/project-roadmap.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/system-architecture.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/activity_context_binding.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/core_events.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/hitl.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/otel_setup.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/span_processor.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/tool_activity_binding.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/trace_context_registry.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/tracing.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/types.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/verdict_handler.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/sonar-project.properties +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/conftest.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/README.md +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/__init__.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/capture_harness.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/chain_completed.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/chain_completed.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/chain_started.handbuilt_serialization_pin.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/chain_started.handbuilt_serialization_pin.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/fake_agent_graphs.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/generate_fixtures.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/graph_capture_harness.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_signed.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_signed.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_unsigned.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_unsigned.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/id_normalization.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/layer1_handbuilt_pins.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_completed.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_completed.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_started.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_started.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/ordering_single_llm_turn.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/ordering_tool_call_turn.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/ordering_two_llm_calls_turn.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/real_emitted_event_fixtures.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/signal_received.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/signal_received.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_completed.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_completed.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_started.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_started.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_completed.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_completed.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_started.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_started.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_completed_error_close.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_completed_error_close.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_failed.handbuilt_serialization_pin.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_failed.handbuilt_serialization_pin.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_started.normalized.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_started.raw.json +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_activity_context_binding.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_agent_identity.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_approval_strict_parsing.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_client_shim_compat.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_config_client_core.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_config_resolution_precedence.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_context_fallback_task_and_thread.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_context_turn_isolation.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_contextvars_propagation.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_conformance_suite.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_events_envelopes.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_runtime_config.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_did_client_signing.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_fail_open_block_preserved.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_golden_baseline.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_governance_changes.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_halt_run_isolation.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_hook_context_pinning.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_hook_family_exclusivity.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_langchain_callback_dedup.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_langchain_callback_llm_context.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_lifecycle_golden_parity.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_loop_liveness_on_sync_approval.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_recording_client_seam.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_signed_headers_parity.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_types_hook_core.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_verdict_span_hitl_core.py +0 -0
- {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_version_static.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:
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
- Resume approved tools and operation hooks in place, preserving their activity IDs
|
|
6
|
+
and graph state instead of replaying the entire graph from its original input.
|
|
7
|
+
- Handle repeated approval requests through invocation and streaming entry points.
|
|
8
|
+
Share each decision between sync and async callbacks for the same evaluation.
|
|
9
|
+
- Cancel pending sync-tool waits when their turn ends, preventing a late approval
|
|
10
|
+
from executing an abandoned tool. Fail closed for sync waits on the event loop.
|
|
11
|
+
|
|
12
|
+
## 1.1.0
|
|
13
|
+
|
|
14
|
+
- Upgrade `openbox-sdk-python` to `>=1.4.0` for IAM v3 workload identity. Keep
|
|
15
|
+
`openbox-langchain-sdk-python` at `>=1.0.0` (locked to 1.0.0).
|
|
16
|
+
- Update locked AnyIO to 4.14.2 and urllib3 to 2.8.0 in the SDK and demo, plus
|
|
17
|
+
pyasn1 to 0.6.4 in the demo, to address Trivy's critical/high findings.
|
|
18
|
+
- Add `workload_private_key` to initialization, graph creation, runtime creation,
|
|
19
|
+
and standalone governance clients, with framework/global environment support
|
|
20
|
+
during initialization and runtime creation.
|
|
21
|
+
- Delegate workload bootstrap, token exchange, caching, and refresh to the base
|
|
22
|
+
SDK. Reuse the handler's runtime client for validation, sync/raw evaluation,
|
|
23
|
+
and approval polling alongside callbacks and operation hooks.
|
|
24
|
+
- Preserve authentication, signing, and bootstrap/configuration errors under
|
|
25
|
+
fail-open policies. Export `OpenBoxSigningError` with Core's `reason_code`.
|
|
26
|
+
- Preserve legacy DID/API-key configuration and the base SDK's explicit
|
|
27
|
+
no-workload-authority fallback for rolling upgrades.
|
|
28
|
+
|
|
3
29
|
## 0.3.0
|
|
4
30
|
|
|
5
31
|
Migrates the SDK onto the shared `openbox-sdk-python` (`openbox_core`) governance
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: openbox-langgraph-sdk-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: OpenBox governance and observability SDK for LangGraph
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -10,7 +10,7 @@ Requires-Dist: langchain-core>=1.3.3
|
|
|
10
10
|
Requires-Dist: langgraph>=0.2.0
|
|
11
11
|
Requires-Dist: langsmith>=0.8.18
|
|
12
12
|
Requires-Dist: openbox-langchain-sdk-python>=1.0.0
|
|
13
|
-
Requires-Dist: openbox-sdk-python>=1.0
|
|
13
|
+
Requires-Dist: openbox-sdk-python>=1.4.0
|
|
14
14
|
Requires-Dist: opentelemetry-api>=1.20.0
|
|
15
15
|
Requires-Dist: opentelemetry-instrumentation-asyncpg>=0.41b0
|
|
16
16
|
Requires-Dist: opentelemetry-instrumentation-httpx>=0.41b0
|
|
@@ -136,17 +136,14 @@ uv add openbox-langgraph-sdk-python
|
|
|
136
136
|
|
|
137
137
|
### 1. Get your agent credentials
|
|
138
138
|
|
|
139
|
-
Sign in to [dashboard.openbox.ai](https://dashboard.openbox.ai), create an agent called `"MyAgent"`, and copy
|
|
140
|
-
|
|
141
|
-
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.
|
|
142
140
|
|
|
143
141
|
### 2. Set environment variables
|
|
144
142
|
|
|
145
143
|
```bash
|
|
146
144
|
export OPENBOX_URL="https://core.openbox.ai"
|
|
147
145
|
export OPENBOX_API_KEY="obx_live_..."
|
|
148
|
-
export
|
|
149
|
-
export OPENBOX_AGENT_PRIVATE_KEY="..."
|
|
146
|
+
export OPENBOX_WORKLOAD_PRIVATE_KEY="$(cat /path/to/workload-private-key.pem)"
|
|
150
147
|
```
|
|
151
148
|
|
|
152
149
|
### 3. Wrap your graph
|
|
@@ -181,6 +178,50 @@ asyncio.run(main())
|
|
|
181
178
|
|
|
182
179
|
That's it. Your agent now sends governance events to OpenBox on every tool call, LLM prompt, HTTP request, and database query.
|
|
183
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
|
+
|
|
184
225
|
### Try it locally (included test agent)
|
|
185
226
|
|
|
186
227
|
The repository includes a runnable LangGraph test agent under `test-agent/`.
|
|
@@ -207,6 +248,7 @@ See `test-agent/README.md` for setup and run instructions.
|
|
|
207
248
|
| `api_key` | `str` | **required** | API key (`obx_live_*` or `obx_test_*`) |
|
|
208
249
|
| `agent_did` | `str` | `OPENBOX_AGENT_DID` | Agent DID used to sign governance requests |
|
|
209
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 |
|
|
210
252
|
| `agent_name` | `str` | `None` | Agent name as configured in the dashboard |
|
|
211
253
|
| `validate` | `bool` | `True` | Validate API key against server on startup |
|
|
212
254
|
| `on_api_error` | `str` | `"fail_open"` | `"fail_open"` (allow on error) or `"fail_closed"` (block on error) |
|
|
@@ -331,7 +373,17 @@ governed = create_openbox_graph_handler(
|
|
|
331
373
|
)
|
|
332
374
|
```
|
|
333
375
|
|
|
334
|
-
The human approves or rejects from the OpenBox dashboard.
|
|
376
|
+
The human approves or rejects from the OpenBox dashboard. Approval resumes the
|
|
377
|
+
pending tool or hook operation with the same activity ID and graph state. Completed
|
|
378
|
+
nodes and earlier tool side effects are not replayed. Later approval requests wait
|
|
379
|
+
independently, including through `astream_governed` and `astream_events`. Rejection
|
|
380
|
+
raises `ApprovalRejectedError`; expiration raises `ApprovalExpiredError`.
|
|
381
|
+
|
|
382
|
+
Async operations await the decision without blocking the event loop. Synchronous
|
|
383
|
+
tools wait in their executor thread. A synchronous operation called directly on the
|
|
384
|
+
event-loop thread cannot safely suspend its stack, so pending approval raises
|
|
385
|
+
`OpenBoxConfigError`; use an async operation or `asyncio.to_thread()` in that case.
|
|
386
|
+
Cancelling the governed turn also stops pending approval waits.
|
|
335
387
|
|
|
336
388
|
| Key | Type | Default | Description |
|
|
337
389
|
|---|---|---|---|
|
|
@@ -94,17 +94,14 @@ uv add openbox-langgraph-sdk-python
|
|
|
94
94
|
|
|
95
95
|
### 1. Get your agent credentials
|
|
96
96
|
|
|
97
|
-
Sign in to [dashboard.openbox.ai](https://dashboard.openbox.ai), create an agent called `"MyAgent"`, and copy
|
|
98
|
-
|
|
99
|
-
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.
|
|
100
98
|
|
|
101
99
|
### 2. Set environment variables
|
|
102
100
|
|
|
103
101
|
```bash
|
|
104
102
|
export OPENBOX_URL="https://core.openbox.ai"
|
|
105
103
|
export OPENBOX_API_KEY="obx_live_..."
|
|
106
|
-
export
|
|
107
|
-
export OPENBOX_AGENT_PRIVATE_KEY="..."
|
|
104
|
+
export OPENBOX_WORKLOAD_PRIVATE_KEY="$(cat /path/to/workload-private-key.pem)"
|
|
108
105
|
```
|
|
109
106
|
|
|
110
107
|
### 3. Wrap your graph
|
|
@@ -139,6 +136,50 @@ asyncio.run(main())
|
|
|
139
136
|
|
|
140
137
|
That's it. Your agent now sends governance events to OpenBox on every tool call, LLM prompt, HTTP request, and database query.
|
|
141
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
|
+
|
|
142
183
|
### Try it locally (included test agent)
|
|
143
184
|
|
|
144
185
|
The repository includes a runnable LangGraph test agent under `test-agent/`.
|
|
@@ -165,6 +206,7 @@ See `test-agent/README.md` for setup and run instructions.
|
|
|
165
206
|
| `api_key` | `str` | **required** | API key (`obx_live_*` or `obx_test_*`) |
|
|
166
207
|
| `agent_did` | `str` | `OPENBOX_AGENT_DID` | Agent DID used to sign governance requests |
|
|
167
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 |
|
|
168
210
|
| `agent_name` | `str` | `None` | Agent name as configured in the dashboard |
|
|
169
211
|
| `validate` | `bool` | `True` | Validate API key against server on startup |
|
|
170
212
|
| `on_api_error` | `str` | `"fail_open"` | `"fail_open"` (allow on error) or `"fail_closed"` (block on error) |
|
|
@@ -289,7 +331,17 @@ governed = create_openbox_graph_handler(
|
|
|
289
331
|
)
|
|
290
332
|
```
|
|
291
333
|
|
|
292
|
-
The human approves or rejects from the OpenBox dashboard.
|
|
334
|
+
The human approves or rejects from the OpenBox dashboard. Approval resumes the
|
|
335
|
+
pending tool or hook operation with the same activity ID and graph state. Completed
|
|
336
|
+
nodes and earlier tool side effects are not replayed. Later approval requests wait
|
|
337
|
+
independently, including through `astream_governed` and `astream_events`. Rejection
|
|
338
|
+
raises `ApprovalRejectedError`; expiration raises `ApprovalExpiredError`.
|
|
339
|
+
|
|
340
|
+
Async operations await the decision without blocking the event loop. Synchronous
|
|
341
|
+
tools wait in their executor thread. A synchronous operation called directly on the
|
|
342
|
+
event-loop thread cannot safely suspend its stack, so pending approval raises
|
|
343
|
+
`OpenBoxConfigError`; use an async operation or `asyncio.to_thread()` in that case.
|
|
344
|
+
Cancelling the governed turn also stops pending approval waits.
|
|
293
345
|
|
|
294
346
|
| Key | Type | Default | Description |
|
|
295
347
|
|---|---|---|---|
|