agent-workflow-sdk 0.2.0__tar.gz → 0.3.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 (167) hide show
  1. agent_workflow_sdk-0.3.0/.github/ISSUE_TEMPLATE/bug_report.md +30 -0
  2. agent_workflow_sdk-0.3.0/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  3. agent_workflow_sdk-0.3.0/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/.github/workflows/ci.yml +36 -0
  5. agent_workflow_sdk-0.3.0/.github/workflows/docs.yml +48 -0
  6. agent_workflow_sdk-0.3.0/.github/workflows/release.yml +88 -0
  7. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/CHANGELOG.md +44 -2
  8. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/PKG-INFO +110 -42
  9. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/README.md +111 -43
  10. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/__init__.py +2 -2
  11. agent_workflow_sdk-0.3.0/agentflow/_pg.py +79 -0
  12. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/_serde.py +2 -0
  13. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/base.py +21 -0
  14. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/postgres.py +27 -14
  15. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/compiled.py +46 -0
  16. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/memory.py +14 -1
  17. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/postgres.py +54 -27
  18. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/queue.py +10 -5
  19. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/records.py +11 -3
  20. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/worker.py +13 -10
  21. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/errors.py +8 -3
  22. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/__init__.py +12 -0
  23. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/effects.py +1 -3
  24. agent_workflow_sdk-0.3.0/agentflow/prebuilt/watch.py +238 -0
  25. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/runtime.py +27 -2
  26. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/state.py +1 -1
  27. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/store/postgres.py +31 -18
  28. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/patterns/long-running-loops.md +39 -0
  29. agent_workflow_sdk-0.3.0/docs/reference/api/watch.md +12 -0
  30. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/research_plan_implement_review.py +17 -6
  31. agent_workflow_sdk-0.3.0/examples/watch_until_done.py +101 -0
  32. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/mkdocs.yml +1 -0
  33. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/pyproject.toml +7 -5
  34. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/conftest.py +30 -0
  35. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_gate.py +1 -3
  36. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_idempotent.py +2 -6
  37. agent_workflow_sdk-0.3.0/tests/test_postgres_checkpointer.py +167 -0
  38. agent_workflow_sdk-0.3.0/tests/test_postgres_runqueue.py +324 -0
  39. agent_workflow_sdk-0.3.0/tests/test_postgres_store.py +169 -0
  40. agent_workflow_sdk-0.3.0/tests/test_watch.py +213 -0
  41. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/.env.example +0 -0
  42. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/.gitignore +0 -0
  43. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/CONTRIBUTING.md +0 -0
  44. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/DESIGN.md +0 -0
  45. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/LICENSE +0 -0
  46. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/NOTICE +0 -0
  47. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/SECURITY.md +0 -0
  48. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/__init__.py +0 -0
  49. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/_http.py +0 -0
  50. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/anthropic.py +0 -0
  51. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/base.py +0 -0
  52. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/claude_code.py +0 -0
  53. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/cli_exec.py +0 -0
  54. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/codex.py +0 -0
  55. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/kiro.py +0 -0
  56. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/ollama.py +0 -0
  57. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/backends/openai.py +0 -0
  58. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/__init__.py +0 -0
  59. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/file.py +0 -0
  60. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/memory.py +0 -0
  61. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/redis.py +0 -0
  62. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/checkpoint/sqlite.py +0 -0
  63. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/__init__.py +0 -0
  64. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/controlplane/registry.py +0 -0
  65. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/events.py +0 -0
  66. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/graph.py +0 -0
  67. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/interrupts.py +0 -0
  68. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/observability.py +0 -0
  69. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/otel.py +0 -0
  70. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/gate.py +0 -0
  71. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/idempotent.py +0 -0
  72. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/loop.py +0 -0
  73. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/resilience.py +0 -0
  74. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prebuilt/tool_loop.py +0 -0
  75. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/prometheus.py +0 -0
  76. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/py.typed +0 -0
  77. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/redaction.py +0 -0
  78. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/store/__init__.py +0 -0
  79. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/store/_util.py +0 -0
  80. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/store/base.py +0 -0
  81. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/store/memory.py +0 -0
  82. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/agentflow/telemetry.py +0 -0
  83. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/backends/agent-backends.md +0 -0
  84. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/backends/llm-backends.md +0 -0
  85. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/backends/overview.md +0 -0
  86. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/backends/permissions.md +0 -0
  87. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/backends/retries.md +0 -0
  88. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/concepts/context.md +0 -0
  89. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/concepts/execution.md +0 -0
  90. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/concepts/nodes-and-edges.md +0 -0
  91. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/concepts/running.md +0 -0
  92. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/concepts/state.md +0 -0
  93. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/concepts/subgraphs.md +0 -0
  94. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/durability/checkpointing.md +0 -0
  95. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/durability/control-plane.md +0 -0
  96. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/durability/human-in-the-loop.md +0 -0
  97. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/durability/observability.md +0 -0
  98. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/durability/quality-gates.md +0 -0
  99. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/durability/store.md +0 -0
  100. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/get-started/installation.md +0 -0
  101. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/get-started/mental-model.md +0 -0
  102. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/get-started/overview.md +0 -0
  103. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/get-started/quickstart.md +0 -0
  104. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/index.md +0 -0
  105. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/patterns/prebuilt.md +0 -0
  106. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/patterns/tutorial-qa-agent.md +0 -0
  107. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/backends.md +0 -0
  108. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/checkpoint.md +0 -0
  109. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/compiled.md +0 -0
  110. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/controlplane.md +0 -0
  111. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/errors.md +0 -0
  112. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/events.md +0 -0
  113. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/gate.md +0 -0
  114. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/graph.md +0 -0
  115. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/interrupts.md +0 -0
  116. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/observability.md +0 -0
  117. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/permissions.md +0 -0
  118. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/prebuilt.md +0 -0
  119. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/runtime.md +0 -0
  120. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/state.md +0 -0
  121. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api/store.md +0 -0
  122. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/api.md +0 -0
  123. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/docs/reference/glossary.md +0 -0
  124. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/agents_demo.py +0 -0
  125. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/codebase_qa_ollama.py +0 -0
  126. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/hello_graph.py +0 -0
  127. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/hitl_permission.py +0 -0
  128. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/idempotent_effect.py +0 -0
  129. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/mixed_backends.py +0 -0
  130. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/optimize_loop.py +0 -0
  131. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/quality_gate.py +0 -0
  132. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/telemetry_demo.py +0 -0
  133. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/examples/tool_loop_ollama.py +0 -0
  134. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_anthropic_backend.py +0 -0
  135. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_backend_lifecycle.py +0 -0
  136. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_checkpoint_contract.py +0 -0
  137. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_cli_backends.py +0 -0
  138. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_concurrency.py +0 -0
  139. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_controlplane.py +0 -0
  140. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_effects.py +0 -0
  141. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_graph_engine.py +0 -0
  142. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_hitl_permission.py +0 -0
  143. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_http_retry.py +0 -0
  144. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_input_validation.py +0 -0
  145. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_kiro_backend.py +0 -0
  146. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_live_backends.py +0 -0
  147. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_observability.py +0 -0
  148. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_ollama_backend.py +0 -0
  149. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_openai_backend.py +0 -0
  150. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_otel.py +0 -0
  151. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_permission_policy.py +0 -0
  152. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_prebuilt_loop.py +0 -0
  153. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_prebuilt_no_httpx.py +0 -0
  154. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_prometheus.py +0 -0
  155. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_provider_resilience.py +0 -0
  156. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_redaction.py +0 -0
  157. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_redis_checkpointer.py +0 -0
  158. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_resilience.py +0 -0
  159. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_run_timeout.py +0 -0
  160. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_sqlite_checkpointer.py +0 -0
  161. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_state_isolation.py +0 -0
  162. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_step_atomicity.py +0 -0
  163. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_store.py +0 -0
  164. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_subgraph.py +0 -0
  165. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_sync_facade.py +0 -0
  166. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_telemetry.py +0 -0
  167. {agent_workflow_sdk-0.2.0 → agent_workflow_sdk-0.3.0}/tests/test_tool_loop.py +0 -0
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something behaves incorrectly or crashes
4
+ labels: bug
5
+ ---
6
+
7
+ ## What happened
8
+
9
+ A clear description of the bug and what you expected instead.
10
+
11
+ ## Reproduction
12
+
13
+ Smallest graph/code that reproduces it. A runnable snippet is ideal.
14
+
15
+ ```python
16
+ # ...
17
+ ```
18
+
19
+ ## Environment
20
+
21
+ - `agent-workflow-sdk` version:
22
+ - Python version:
23
+ - Backend involved (KiroBackend / CodexBackend / ClaudeCodeBackend / OllamaBackend / OpenAIBackend / AnthropicBackend / none):
24
+ - Checkpointer / Store / control-plane backend, if relevant (memory / file / sqlite / redis / postgres):
25
+
26
+ ## Logs or traceback
27
+
28
+ ```
29
+ paste here
30
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: Feature request
3
+ about: Propose a capability or change
4
+ labels: enhancement
5
+ ---
6
+
7
+ ## Problem
8
+
9
+ What are you trying to do that the SDK makes hard or impossible today?
10
+
11
+ ## Proposed solution
12
+
13
+ What you'd like to see. If it touches the public API, sketch the shape
14
+ (a node, a backend, a prebuilt pattern, a control-plane method, ...).
15
+
16
+ ## Alternatives considered
17
+
18
+ Workarounds you've tried, or other designs you weighed.
19
+
20
+ ## Scope check
21
+
22
+ Does this fit a library (engine, backends, control plane) rather than a
23
+ service layer? See `DESIGN.md` for what is intentionally out of scope.
@@ -0,0 +1,17 @@
1
+ ## What and why
2
+
3
+ What this changes and the problem it solves. Link any related issue.
4
+
5
+ ## How
6
+
7
+ Key implementation points a reviewer should know. Note any new public API
8
+ or any change to a documented contract in `DESIGN.md`.
9
+
10
+ ## Checklist
11
+
12
+ - [ ] `ruff check agentflow tests examples` passes
13
+ - [ ] `ruff format --check agentflow tests examples` passes
14
+ - [ ] `mypy agentflow` passes
15
+ - [ ] `pytest -q` (offline suite) passes; added/updated tests for the change
16
+ - [ ] Docs updated if behavior or public API changed (README / `docs/` / docstrings)
17
+ - [ ] `CHANGELOG.md` updated under `[Unreleased]` for a user-facing change
@@ -78,3 +78,39 @@ jobs:
78
78
  assert "agentflow/py.typed" in names, "py.typed missing from wheel"
79
79
  print("py.typed present in", wheel)
80
80
  PY
81
+
82
+ pg-tests:
83
+ # The Postgres backends (Store, Checkpointer, RunQueue) are skipped by the
84
+ # hermetic default run, so their real SQL paths are exercised here against
85
+ # a live server started as a service container.
86
+ runs-on: ubuntu-latest
87
+ services:
88
+ postgres:
89
+ image: postgres:16
90
+ env:
91
+ POSTGRES_USER: postgres
92
+ POSTGRES_PASSWORD: postgres
93
+ POSTGRES_DB: agentflow_test
94
+ ports:
95
+ - 5432:5432
96
+ options: >-
97
+ --health-cmd pg_isready
98
+ --health-interval 5s
99
+ --health-timeout 5s
100
+ --health-retries 10
101
+ steps:
102
+ - uses: actions/checkout@v4
103
+ - uses: actions/setup-python@v5
104
+ with:
105
+ python-version: "3.11"
106
+ - name: Install (postgres + ollama + dev extras)
107
+ # ollama is included for httpx: pytest imports every test module during
108
+ # collection, and the HTTP-backend test modules import httpx at top
109
+ # level — without it, collection errors before the -m pg filter applies.
110
+ run: |
111
+ python -m pip install --upgrade pip
112
+ pip install -e '.[postgres,ollama,dev]'
113
+ - name: Run the Postgres test suite
114
+ env:
115
+ POSTGRES_TEST_DSN: postgresql://postgres:postgres@localhost:5432/agentflow_test
116
+ run: pytest -q -m pg tests/test_postgres_store.py tests/test_postgres_checkpointer.py tests/test_postgres_runqueue.py
@@ -0,0 +1,48 @@
1
+ name: Docs
2
+
3
+ # Build the mkdocs site and deploy it to GitHub Pages on a version tag, or on
4
+ # demand from the Actions tab. Enable Pages once (Settings -> Pages -> Source:
5
+ # GitHub Actions) for the deploy step to publish.
6
+ on:
7
+ push:
8
+ tags:
9
+ - "v*"
10
+ workflow_dispatch:
11
+
12
+ # Allow one concurrent deploy; a newer run supersedes an in-flight one.
13
+ concurrency:
14
+ group: pages
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.11"
25
+ - name: Install docs extra
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install -e '.[docs]'
29
+ - name: Build the site (strict)
30
+ run: mkdocs build --strict
31
+ - name: Upload the Pages artifact
32
+ uses: actions/upload-pages-artifact@v3
33
+ with:
34
+ path: site
35
+
36
+ deploy:
37
+ needs: build
38
+ runs-on: ubuntu-latest
39
+ permissions:
40
+ pages: write
41
+ id-token: write
42
+ environment:
43
+ name: github-pages
44
+ url: ${{ steps.deployment.outputs.page_url }}
45
+ steps:
46
+ - name: Deploy to GitHub Pages
47
+ id: deployment
48
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,88 @@
1
+ name: Release
2
+
3
+ # Publish to PyPI and cut a GitHub Release when a version tag is pushed.
4
+ on:
5
+ push:
6
+ tags:
7
+ - "v*"
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+
18
+ - name: Verify the tag matches the packaged version
19
+ # A tag of vX.Y.Z must match pyproject's version and __version__, so a
20
+ # mistagged release fails here instead of publishing the wrong build.
21
+ run: |
22
+ python -m pip install --upgrade pip
23
+ tag="${GITHUB_REF_NAME#v}"
24
+ proj=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
25
+ pkg=$(python -c "import re; print(re.search(r'__version__ = \"([^\"]+)\"', open('agentflow/__init__.py').read()).group(1))")
26
+ echo "tag=$tag pyproject=$proj package=$pkg"
27
+ test "$tag" = "$proj" || { echo "tag != pyproject version"; exit 1; }
28
+ test "$tag" = "$pkg" || { echo "tag != __version__"; exit 1; }
29
+
30
+ - name: Build wheel + sdist
31
+ run: |
32
+ python -m pip install build
33
+ python -m build
34
+
35
+ - name: Check artifacts (twine + py.typed)
36
+ run: |
37
+ python -m pip install twine
38
+ python -m twine check dist/*
39
+ python - <<'PY'
40
+ import glob, zipfile
41
+ wheel = glob.glob("dist/*.whl")[0]
42
+ assert "agentflow/py.typed" in zipfile.ZipFile(wheel).namelist(), "py.typed missing"
43
+ print("py.typed present in", wheel)
44
+ PY
45
+
46
+ - name: Upload built artifacts
47
+ uses: actions/upload-artifact@v4
48
+ with:
49
+ name: dist
50
+ path: dist/
51
+
52
+ publish-pypi:
53
+ needs: build
54
+ runs-on: ubuntu-latest
55
+ # Trusted Publishing (OIDC): no API token stored anywhere. Configure the
56
+ # matching publisher for this repo/workflow on PyPI once (Project settings
57
+ # -> Publishing) and every tagged build publishes with no secret.
58
+ environment: pypi
59
+ permissions:
60
+ id-token: write
61
+ steps:
62
+ - name: Fetch built artifacts
63
+ uses: actions/download-artifact@v4
64
+ with:
65
+ name: dist
66
+ path: dist/
67
+ - name: Publish to PyPI
68
+ uses: pypa/gh-action-pypi-publish@release/v1
69
+
70
+ github-release:
71
+ needs: publish-pypi
72
+ runs-on: ubuntu-latest
73
+ permissions:
74
+ contents: write
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+ - name: Fetch built artifacts
78
+ uses: actions/download-artifact@v4
79
+ with:
80
+ name: dist
81
+ path: dist/
82
+ - name: Create the GitHub Release
83
+ env:
84
+ GH_TOKEN: ${{ github.token }}
85
+ run: |
86
+ gh release create "$GITHUB_REF_NAME" dist/* \
87
+ --title "$GITHUB_REF_NAME" \
88
+ --notes "See [CHANGELOG.md](https://github.com/${GITHUB_REPOSITORY}/blob/main/CHANGELOG.md) for what changed."
@@ -4,6 +4,48 @@ All notable changes to `agent-workflow-sdk` are documented here. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
5
5
  project aims to follow [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [0.3.0] - 2026-10-02
8
+
9
+ ### Added
10
+
11
+ - Watch nodes: park a run on an external system without burning turns while
12
+ nothing changes. `ctx.wait(wake_at, payload)` is a timer-based sibling of the
13
+ human interrupt — it suspends the run until a time, then re-runs the node.
14
+ `Checkpoint` gains `wake_at` and a derived `suspend_kind` (`"human"` |
15
+ `"timer"`); the human-interrupt path is unchanged.
16
+ - Durable parked execution: `RunStatus.WAITING` + `RunRecord.wake_at`. A run
17
+ parked on `ctx.wait` is `WAITING` in the queue and does not hold a worker;
18
+ `claim` re-takes it once `wake_at` passes (symmetric to lease expiry), in both
19
+ `MemoryRunQueue` and `PostgresRunQueue`. The worker frees itself on a timer
20
+ suspend and resumes on re-claim.
21
+ - `CompiledGraph.run_until_done(...)` drives timer waits inline (sleeps until
22
+ `wake_at` and resumes), for running a watch loop without the control plane —
23
+ the process must stay alive for the wait, unlike the parked control-plane
24
+ path.
25
+ - `agentflow.prebuilt.watch`: `WatchResult` (idle/activity/terminal), the
26
+ `Watcher` protocol, `CommandWatcher` (poll any command that prints the
27
+ contract JSON), `watch_node` (polls, parks on idle, loops until non-idle), and
28
+ `route_watch`. GitHub/CI/etc. are examples over `CommandWatcher`, not core.
29
+ See `examples/watch_until_done.py`.
30
+
31
+ ### Fixed
32
+
33
+ - First-use schema creation on PostgreSQL is now concurrency-safe. `CREATE TABLE
34
+ IF NOT EXISTS` can collide on `pg_type` when two sessions bootstrap the same
35
+ table at once; the Postgres backends now run that DDL under a
36
+ `pg_advisory_xact_lock` (plus an in-process lock), so a pool of workers
37
+ starting together no longer races.
38
+
39
+ ### Changed
40
+
41
+ - Internal: the Postgres backends (`PostgresStore`, `PostgresCheckpointer`,
42
+ `PostgresRunQueue`) now have a real-server contract test suite, run in CI
43
+ against a `postgres` service container. The tests are marked `pg` and skipped
44
+ by the default hermetic run (they need `POSTGRES_TEST_DSN`); they cover the
45
+ SQL-only paths the in-memory suites can't — the `if_absent` conditional write
46
+ and `StoreConflict`, the `if_revision` compare-and-set and `CheckpointConflict`,
47
+ and concurrent `claim` under `FOR UPDATE SKIP LOCKED`.
48
+
7
49
  ## [0.2.0] - 2026-10-01
8
50
 
9
51
  ### Added
@@ -99,8 +141,8 @@ project aims to follow [Semantic Versioning](https://semver.org/).
99
141
 
100
142
  ## [0.1.0] - 2026-09-29
101
143
 
102
- First public release: an async-first, LangGraph-style SDK for agent workflows
103
- with pluggable agent and LLM backends.
144
+ First public release: an async-first SDK for agent workflows with pluggable
145
+ agent and LLM backends.
104
146
 
105
147
  ### Added
106
148
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agent-workflow-sdk
3
- Version: 0.2.0
4
- Summary: Async-first, LangGraph-style SDK for building agent workflows with pluggable agent and LLM backends.
3
+ Version: 0.3.0
4
+ Summary: Async-first SDK for orchestrating local coding-agent CLIs (Claude Code, Codex, Kiro) and LLMs as durable, graph-based workflows.
5
5
  Project-URL: Homepage, https://github.com/dankosorkin/agent-workflow-sdk
6
6
  Project-URL: Repository, https://github.com/dankosorkin/agent-workflow-sdk
7
7
  Project-URL: Changelog, https://github.com/dankosorkin/agent-workflow-sdk/blob/main/CHANGELOG.md
@@ -45,69 +45,137 @@ Description-Content-Type: text/markdown
45
45
 
46
46
  # agent-workflow-sdk
47
47
 
48
- An async-first, LangGraph-style SDK for building agent workflows from
49
- composable pieces. You describe a workflow as a graph of nodes over a typed,
50
- reducer-based state, and run it against a pluggable backend — a coding agent
51
- (Kiro, Codex, or Claude Code) or a plain LLM (Ollama, any OpenAI-compatible
52
- endpoint, or Anthropic).
48
+ [![PyPI](https://img.shields.io/pypi/v/agent-workflow-sdk)](https://pypi.org/project/agent-workflow-sdk/)
49
+ [![Python](https://img.shields.io/pypi/pyversions/agent-workflow-sdk)](https://pypi.org/project/agent-workflow-sdk/)
50
+ [![CI](https://github.com/dankosorkin/agent-workflow-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/dankosorkin/agent-workflow-sdk/actions/workflows/ci.yml)
51
+ [![License](https://img.shields.io/pypi/l/agent-workflow-sdk)](LICENSE)
52
+ [![Docs](https://img.shields.io/badge/docs-live-brightgreen)](https://dankosorkin.github.io/agent-workflow-sdk/)
53
53
 
54
- The import root is `agentflow`. The distribution name is
55
- `agent-workflow-sdk`.
54
+ An async-first SDK for building agent workflows from composable pieces. You
55
+ describe a workflow as a graph of nodes over a typed, reducer-based state, and
56
+ run it against a pluggable backend — a local coding agent (Claude Code, Codex,
57
+ or Kiro) or a plain LLM (Ollama, any OpenAI-compatible endpoint, or Anthropic).
56
58
 
57
- ## Why
59
+ The import root is `agentflow`. The distribution name is `agent-workflow-sdk`.
58
60
 
59
- - Build any workflow from primitives: nodes, edges, conditional routing, and
60
- a shared state. Not a fixed loop, not a linear chain.
61
+ ## Who it's for
62
+
63
+ You drive a **local coding-agent CLI** — Claude Code, Codex, or Kiro — and you
64
+ want to orchestrate it with real control flow: branches, loops, retries, a
65
+ human approving a step, a run that survives a crash and resumes. You get that
66
+ without wiring up an API key, because the agent runs through its own CLI and
67
+ its own auth. (An API key path exists too — point a node at `OpenAIBackend` or
68
+ `AnthropicBackend` when you want one — but it's an option, not a requirement.)
69
+
70
+ It is a library, not a coding agent out of the box. If a ready-made agent CLI
71
+ already does what you need, use that. Reach for this when you need to build the
72
+ workflow *around* the agent and keep that logic independent of which backend
73
+ runs underneath.
74
+
75
+ - Build any workflow from primitives: nodes, edges, conditional routing, and a
76
+ shared state. Not a fixed loop, not a linear chain.
61
77
  - Swap the backend without touching workflow code. Agents and LLMs share one
62
78
  event vocabulary.
63
79
  - Async everywhere: the engine, backends, checkpointing, and streaming.
64
80
  - Durable by default: every super-step is checkpointed, runs resume after a
65
81
  crash, and human-in-the-loop interrupts suspend and resume a run.
66
82
 
67
-
68
83
  ## Install
69
84
 
85
+ ```bash
86
+ pip install agent-workflow-sdk
87
+ ```
88
+
70
89
  The core is dependency-free. Backends that need extra libraries are optional
71
- extras.
90
+ extras — e.g. `pip install 'agent-workflow-sdk[ollama]'` for the HTTP LLM
91
+ backends. Python 3.11+ is required.
92
+
93
+ The local-agent backends need their CLI on PATH: `claude` for Claude Code,
94
+ `codex` for Codex, `kiro-cli` for Kiro. No API key is needed — each CLI uses
95
+ its own login.
96
+
97
+ To work on the SDK itself, clone and install editable:
72
98
 
73
99
  ```bash
74
- pip install -e . # core only
75
- pip install -e '.[ollama]' # + httpx, for the Ollama LLM backend
76
- pip install -e '.[dev]' # + pytest, pytest-asyncio
100
+ git clone https://github.com/dankosorkin/agent-workflow-sdk
101
+ cd agent-workflow-sdk
102
+ pip install -e '.[dev]'
77
103
  ```
78
104
 
79
- Python 3.11+ is required. The Kiro backend needs `kiro-cli` on PATH.
105
+ ## Quickstart: a local agent, gated by a human
80
106
 
81
- ## Quickstart
82
-
83
- A graph that loops until a counter reaches a target, then stops.
107
+ A two-step workflow that puts the SDK's point on one screen. A **Claude Code**
108
+ node does the work in its own session; then the run **pauses for a human** to
109
+ approve before anything proceeds. Because every step is checkpointed, the
110
+ pause survives a process restart — you can approve now, tomorrow, or from a
111
+ different process, and the run resumes exactly where it stopped. No API key:
112
+ Claude Code runs through its own CLI login.
84
113
 
85
114
  ```python
86
115
  import asyncio
87
116
  from typing import Annotated
88
- from agentflow import Graph, START, END, State, add, append
89
-
90
- class CountState(State):
91
- n: Annotated[int, add] # updates are summed
92
- log: Annotated[list, append] # updates are concatenated
93
-
94
- async def tick(state, ctx):
95
- return {"n": 1, "log": f"tick {state.get('n', 0) + 1}"}
96
-
97
- def route(state):
98
- return "again" if state["n"] < 5 else "done"
99
-
100
- g = Graph(CountState)
101
- g.add_node("tick", tick)
102
- g.add_edge(START, "tick")
103
- g.add_conditional_edges("tick", route, {"again": "tick", "done": END})
104
- app = g.compile()
105
-
106
- print(asyncio.run(app.invoke({"n": 0, "log": []})))
117
+ from agentflow import Graph, START, END, State, FileCheckpointer, last, append
118
+ from agentflow.backends.claude_code import ClaudeCodeBackend
119
+ from agentflow.backends.base import DenyAll
120
+ from agentflow.events import TextChunk, TurnEnd
121
+
122
+ class ReviewState(State):
123
+ target: Annotated[str, last]
124
+ proposal: Annotated[str, last]
125
+ approved: Annotated[bool, last]
126
+ log: Annotated[list, append]
127
+
128
+ claude = ClaudeCodeBackend(model="sonnet", permission=DenyAll()) # read-only
129
+
130
+ async def propose(state, ctx):
131
+ text = []
132
+ async for ev in claude.prompt(
133
+ f"Review this repo and propose ONE concrete improvement to {state['target']}. "
134
+ "Describe the change; do not apply it."
135
+ ):
136
+ if isinstance(ev, TextChunk):
137
+ ctx.emit(ev) # stream tokens to the caller as they arrive
138
+ text.append(ev.text)
139
+ elif isinstance(ev, TurnEnd):
140
+ text = [ev.text] if ev.text else text
141
+ return {"proposal": "".join(text)}
142
+
143
+ async def gate(state, ctx):
144
+ # Suspend the whole run until a human answers. On a fresh run this stops
145
+ # here and checkpoints; on resume, interrupt() returns the human's value.
146
+ decision = await ctx.interrupt({"review": state["proposal"]})
147
+ return {"approved": decision == "approve", "log": f"human said: {decision}"}
148
+
149
+ g = Graph(ReviewState)
150
+ g.add_node("propose", propose)
151
+ g.add_node("gate", gate)
152
+ g.add_edge(START, "propose")
153
+ g.add_edge("propose", "gate")
154
+ g.add_edge("gate", END)
155
+
156
+ async def main():
157
+ app = g.compile(checkpointer=FileCheckpointer(".runs")) # durable
158
+ async with claude:
159
+ state = await app.invoke({"target": "the README"}, thread="demo")
160
+ # The run is now parked at the gate. Show the proposal, get a decision:
161
+ cp = await app.get_state("demo")
162
+ print(cp.interrupt_payload["review"]) # Claude's proposal
163
+ final = await app.resume("demo", value="approve")
164
+ print(final["approved"], final["log"])
165
+
166
+ asyncio.run(main())
107
167
  ```
108
168
 
109
- See `examples/hello_graph.py` and `examples/optimize_loop.py` for runnable
110
- versions.
169
+ That is the whole value in one example: a real local agent does the work, the
170
+ graph owns the control flow, a human gates the result, and durability means
171
+ the pause is not tied to this process staying alive. Swap `ClaudeCodeBackend`
172
+ for `CodexBackend`, `KiroBackend`, or an LLM backend and the workflow code
173
+ above does not change.
174
+
175
+ Prefer to learn the engine first, with no backend and nothing to install
176
+ beyond the core? `examples/hello_graph.py` is a minimal counter graph that
177
+ shows state, reducers, and edges on their own; `examples/optimize_loop.py`
178
+ shows the iterate-until-converged loop.
111
179
 
112
180
  ## Core concepts
113
181