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.
Files changed (140) hide show
  1. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.coverage +0 -0
  2. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/pr-quality.yml +1 -1
  3. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/publish.yml +1 -1
  4. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/CHANGELOG.md +26 -0
  5. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/PKG-INFO +61 -9
  6. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/README.md +58 -6
  7. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/coverage.xml +1100 -894
  8. openbox_langgraph_sdk_python-1.2.0/demo/demo_04_content_builder_langgraph/.env.example +16 -0
  9. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/uv.lock +75 -62
  10. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/__init__.py +3 -1
  11. openbox_langgraph_sdk_python-1.2.0/openbox_langgraph/activity_approval.py +156 -0
  12. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/client.py +105 -20
  13. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/config.py +55 -1
  14. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/core_adapter.py +34 -77
  15. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/core_runtime.py +7 -1
  16. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/errors.py +30 -1
  17. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/identity.py +14 -0
  18. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/langgraph_handler.py +34 -147
  19. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/langgraph_hook_runtime.py +9 -0
  20. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/pyproject.toml +2 -2
  21. openbox_langgraph_sdk_python-1.2.0/tests/test_activity_approval_waiter.py +98 -0
  22. openbox_langgraph_sdk_python-1.2.0/tests/test_approval_in_place.py +196 -0
  23. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_context_cleanup_on_error.py +13 -20
  24. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_context_binding.py +12 -1
  25. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_framework_adapter_translation.py +14 -0
  26. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_gate_error_translation.py +35 -3
  27. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_hook_approval_retry.py +27 -83
  28. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_langchain_callback_tool_ordering.py +20 -46
  29. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_public_exports_baseline.py +3 -2
  30. openbox_langgraph_sdk_python-1.2.0/tests/test_workload_identity.py +500 -0
  31. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/uv.lock +72 -59
  32. openbox_langgraph_sdk_python-1.0.0/demo/demo_04_content_builder_langgraph/.env.example +0 -11
  33. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/CODEOWNERS +0 -0
  34. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/pr-governance.yml +0 -0
  35. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.github/workflows/pr-security.yml +0 -0
  36. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.gitignore +0 -0
  37. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/.gitleaks.toml +0 -0
  38. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/AGENTS.md +0 -0
  39. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/CLAUDE.md +0 -0
  40. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/CODE_OF_CONDUCT.md +0 -0
  41. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/LICENSE +0 -0
  42. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/SECURITY.md +0 -0
  43. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/.gitignore +0 -0
  44. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/AGENTS.md +0 -0
  45. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/README.md +0 -0
  46. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/demo/demo_04_content_builder_langgraph/pyproject.toml +0 -0
  47. {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
  48. {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
  49. {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
  50. {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
  51. {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
  52. {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
  53. {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
  54. {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
  55. {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
  56. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/code-standards.md +0 -0
  57. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/codebase-summary.md +0 -0
  58. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/project-overview-pdr.md +0 -0
  59. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/project-roadmap.md +0 -0
  60. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/docs/system-architecture.md +0 -0
  61. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/activity_context_binding.py +0 -0
  62. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/core_events.py +0 -0
  63. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/hitl.py +0 -0
  64. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/otel_setup.py +0 -0
  65. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/span_processor.py +0 -0
  66. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/tool_activity_binding.py +0 -0
  67. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/trace_context_registry.py +0 -0
  68. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/tracing.py +0 -0
  69. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/types.py +0 -0
  70. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/openbox_langgraph/verdict_handler.py +0 -0
  71. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/sonar-project.properties +0 -0
  72. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/conftest.py +0 -0
  73. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/README.md +0 -0
  74. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/__init__.py +0 -0
  75. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/capture_harness.py +0 -0
  76. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/chain_completed.normalized.json +0 -0
  77. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/chain_completed.raw.json +0 -0
  78. {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
  79. {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
  80. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/fake_agent_graphs.py +0 -0
  81. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/generate_fixtures.py +0 -0
  82. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/graph_capture_harness.py +0 -0
  83. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_signed.normalized.json +0 -0
  84. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_signed.raw.json +0 -0
  85. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_unsigned.normalized.json +0 -0
  86. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/headers_unsigned.raw.json +0 -0
  87. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/id_normalization.py +0 -0
  88. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/layer1_handbuilt_pins.py +0 -0
  89. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_completed.normalized.json +0 -0
  90. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_completed.raw.json +0 -0
  91. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_started.normalized.json +0 -0
  92. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/llm_started.raw.json +0 -0
  93. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/ordering_single_llm_turn.json +0 -0
  94. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/ordering_tool_call_turn.json +0 -0
  95. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/ordering_two_llm_calls_turn.json +0 -0
  96. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/real_emitted_event_fixtures.py +0 -0
  97. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/signal_received.normalized.json +0 -0
  98. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/signal_received.raw.json +0 -0
  99. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_completed.normalized.json +0 -0
  100. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_completed.raw.json +0 -0
  101. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_started.normalized.json +0 -0
  102. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/subagent_tool_started.raw.json +0 -0
  103. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_completed.normalized.json +0 -0
  104. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_completed.raw.json +0 -0
  105. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_started.normalized.json +0 -0
  106. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/tool_started.raw.json +0 -0
  107. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_completed_error_close.normalized.json +0 -0
  108. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_completed_error_close.raw.json +0 -0
  109. {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
  110. {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
  111. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_started.normalized.json +0 -0
  112. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/golden/workflow_started.raw.json +0 -0
  113. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_activity_context_binding.py +0 -0
  114. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_agent_identity.py +0 -0
  115. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_approval_strict_parsing.py +0 -0
  116. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_client_shim_compat.py +0 -0
  117. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_config_client_core.py +0 -0
  118. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_config_resolution_precedence.py +0 -0
  119. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_context_fallback_task_and_thread.py +0 -0
  120. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_context_turn_isolation.py +0 -0
  121. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_contextvars_propagation.py +0 -0
  122. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_conformance_suite.py +0 -0
  123. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_events_envelopes.py +0 -0
  124. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_core_runtime_config.py +0 -0
  125. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_did_client_signing.py +0 -0
  126. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_fail_open_block_preserved.py +0 -0
  127. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_golden_baseline.py +0 -0
  128. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_governance_changes.py +0 -0
  129. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_halt_run_isolation.py +0 -0
  130. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_hook_context_pinning.py +0 -0
  131. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_hook_family_exclusivity.py +0 -0
  132. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_langchain_callback_dedup.py +0 -0
  133. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_langchain_callback_llm_context.py +0 -0
  134. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_lifecycle_golden_parity.py +0 -0
  135. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_loop_liveness_on_sync_approval.py +0 -0
  136. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_recording_client_seam.py +0 -0
  137. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_signed_headers_parity.py +0 -0
  138. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_types_hook_core.py +0 -0
  139. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_verdict_span_hitl_core.py +0 -0
  140. {openbox_langgraph_sdk_python-1.0.0 → openbox_langgraph_sdk_python-1.2.0}/tests/test_version_static.py +0 -0
@@ -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@master
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@master
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.4
1
+ Metadata-Version: 2.5
2
2
  Name: openbox-langgraph-sdk-python
3
- Version: 1.0.0
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.1
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 the agent API key plus its DID credentials.
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 OPENBOX_AGENT_DID="did:aip:..."
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. The SDK resumes or raises `ApprovalRejectedError` accordingly.
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 the agent API key plus its DID credentials.
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 OPENBOX_AGENT_DID="did:aip:..."
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. The SDK resumes or raises `ApprovalRejectedError` accordingly.
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
  |---|---|---|---|