swarmkit-runtime 1.0.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 (142) hide show
  1. swarmkit_runtime-1.0.0/.gitignore +66 -0
  2. swarmkit_runtime-1.0.0/CLAUDE.md +55 -0
  3. swarmkit_runtime-1.0.0/PKG-INFO +87 -0
  4. swarmkit_runtime-1.0.0/README.md +44 -0
  5. swarmkit_runtime-1.0.0/pyproject.toml +82 -0
  6. swarmkit_runtime-1.0.0/src/swarmkit_runtime/__init__.py +6 -0
  7. swarmkit_runtime-1.0.0/src/swarmkit_runtime/_workspace_runtime.py +308 -0
  8. swarmkit_runtime-1.0.0/src/swarmkit_runtime/archetypes/__init__.py +163 -0
  9. swarmkit_runtime-1.0.0/src/swarmkit_runtime/audit/__init__.py +13 -0
  10. swarmkit_runtime-1.0.0/src/swarmkit_runtime/authoring/__init__.py +10 -0
  11. swarmkit_runtime-1.0.0/src/swarmkit_runtime/authoring/_agent.py +289 -0
  12. swarmkit_runtime-1.0.0/src/swarmkit_runtime/authoring/_prompts.py +486 -0
  13. swarmkit_runtime-1.0.0/src/swarmkit_runtime/authoring/_tools.py +160 -0
  14. swarmkit_runtime-1.0.0/src/swarmkit_runtime/cli/__init__.py +662 -0
  15. swarmkit_runtime-1.0.0/src/swarmkit_runtime/cli/_knowledge.py +283 -0
  16. swarmkit_runtime-1.0.0/src/swarmkit_runtime/cli/_render.py +243 -0
  17. swarmkit_runtime-1.0.0/src/swarmkit_runtime/errors/__init__.py +104 -0
  18. swarmkit_runtime-1.0.0/src/swarmkit_runtime/gaps/__init__.py +107 -0
  19. swarmkit_runtime-1.0.0/src/swarmkit_runtime/governance/__init__.py +115 -0
  20. swarmkit_runtime-1.0.0/src/swarmkit_runtime/governance/_mock.py +98 -0
  21. swarmkit_runtime-1.0.0/src/swarmkit_runtime/governance/agt_provider.py +194 -0
  22. swarmkit_runtime-1.0.0/src/swarmkit_runtime/knowledge/__init__.py +1 -0
  23. swarmkit_runtime-1.0.0/src/swarmkit_runtime/knowledge/__main__.py +5 -0
  24. swarmkit_runtime-1.0.0/src/swarmkit_runtime/knowledge/_server.py +437 -0
  25. swarmkit_runtime-1.0.0/src/swarmkit_runtime/langgraph_compiler/__init__.py +16 -0
  26. swarmkit_runtime-1.0.0/src/swarmkit_runtime/langgraph_compiler/_compiler.py +679 -0
  27. swarmkit_runtime-1.0.0/src/swarmkit_runtime/langgraph_compiler/_panel.py +131 -0
  28. swarmkit_runtime-1.0.0/src/swarmkit_runtime/langgraph_compiler/_skill_executor.py +185 -0
  29. swarmkit_runtime-1.0.0/src/swarmkit_runtime/langgraph_compiler/_state.py +40 -0
  30. swarmkit_runtime-1.0.0/src/swarmkit_runtime/mcp/__init__.py +8 -0
  31. swarmkit_runtime-1.0.0/src/swarmkit_runtime/mcp/_client.py +259 -0
  32. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/__init__.py +45 -0
  33. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_anthropic.py +148 -0
  34. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_google.py +187 -0
  35. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_mock.py +71 -0
  36. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_ollama.py +133 -0
  37. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_openai.py +155 -0
  38. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_openai_compat.py +64 -0
  39. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_registry.py +62 -0
  40. swarmkit_runtime-1.0.0/src/swarmkit_runtime/model_providers/_types.py +76 -0
  41. swarmkit_runtime-1.0.0/src/swarmkit_runtime/resolver/__init__.py +420 -0
  42. swarmkit_runtime-1.0.0/src/swarmkit_runtime/resolver/_resolved.py +85 -0
  43. swarmkit_runtime-1.0.0/src/swarmkit_runtime/resolver/_topology.py +506 -0
  44. swarmkit_runtime-1.0.0/src/swarmkit_runtime/resolver/_triggers.py +100 -0
  45. swarmkit_runtime-1.0.0/src/swarmkit_runtime/review/__init__.py +118 -0
  46. swarmkit_runtime-1.0.0/src/swarmkit_runtime/review/_hitl.py +60 -0
  47. swarmkit_runtime-1.0.0/src/swarmkit_runtime/server.py +134 -0
  48. swarmkit_runtime-1.0.0/src/swarmkit_runtime/skills/__init__.py +242 -0
  49. swarmkit_runtime-1.0.0/src/swarmkit_runtime/skills/_output_validator.py +161 -0
  50. swarmkit_runtime-1.0.0/src/swarmkit_runtime/topology/__init__.py +9 -0
  51. swarmkit_runtime-1.0.0/src/swarmkit_runtime/workspace/__init__.py +231 -0
  52. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/composed-skills/skills/judge-correctness.yaml +27 -0
  53. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/composed-skills/skills/judge-style.yaml +27 -0
  54. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/composed-skills/skills/panel.yaml +29 -0
  55. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/composed-skills/workspace.yaml +5 -0
  56. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/full/archetypes/supervisor-root.yaml +14 -0
  57. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/full/schedules/daily.yaml +10 -0
  58. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/full/skills/audit-log-write.yaml +14 -0
  59. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/full/topologies/hello.yaml +10 -0
  60. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/full/triggers/webhook.yaml +10 -0
  61. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/full/workspace.yaml +8 -0
  62. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/github-mcp/archetypes/github-reader.yaml +26 -0
  63. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/github-mcp/skills/github-issue-read.yaml +18 -0
  64. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/github-mcp/skills/github-pr-read.yaml +18 -0
  65. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/github-mcp/skills/github-repo-read.yaml +18 -0
  66. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/github-mcp/topologies/github-read.yaml +21 -0
  67. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/github-mcp/workspace.yaml +20 -0
  68. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/grouped-skills/skills/capability/github-repo-read.yaml +14 -0
  69. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/grouped-skills/skills/decision/llm-judge.yaml +27 -0
  70. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/grouped-skills/workspace.yaml +8 -0
  71. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/minimal/workspace.yaml +5 -0
  72. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/resolved-tree/archetypes/code-review-worker.yaml +22 -0
  73. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/resolved-tree/archetypes/supervisor-root.yaml +15 -0
  74. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/resolved-tree/skills/code-quality-review.yaml +27 -0
  75. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/resolved-tree/skills/github-repo-read.yaml +14 -0
  76. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/resolved-tree/topologies/review.yaml +30 -0
  77. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/resolved-tree/workspace.yaml +5 -0
  78. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/with-archetypes/archetypes/abstract-worker.yaml +18 -0
  79. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/with-archetypes/archetypes/concrete-worker.yaml +13 -0
  80. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/with-archetypes/skills/audit-log-write.yaml +14 -0
  81. swarmkit_runtime-1.0.0/tests/fixtures/workspaces/with-archetypes/workspace.yaml +5 -0
  82. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-ambiguous/archetypes/worker.yaml +15 -0
  83. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-ambiguous/skills/content-review-a.yaml +19 -0
  84. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-ambiguous/skills/content-review-b.yaml +19 -0
  85. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-ambiguous/topologies/bad.yaml +13 -0
  86. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-ambiguous/workspace.yaml +5 -0
  87. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-no-match/archetypes/expects-decision.yaml +15 -0
  88. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-no-match/skills/capability-only.yaml +14 -0
  89. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-no-match/topologies/bad.yaml +13 -0
  90. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/abstract-no-match/workspace.yaml +5 -0
  91. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/archetype-unknown-skill/archetypes/bad.yaml +13 -0
  92. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/archetype-unknown-skill/workspace.yaml +5 -0
  93. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/composed-cycle/skills/a.yaml +20 -0
  94. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/composed-cycle/skills/b.yaml +20 -0
  95. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/composed-cycle/workspace.yaml +5 -0
  96. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/composed-unknown/skills/broken.yaml +20 -0
  97. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/composed-unknown/workspace.yaml +5 -0
  98. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/deep-nesting/skills/a/b/too-deep.yaml +16 -0
  99. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/deep-nesting/workspace.yaml +5 -0
  100. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-agent-id/topologies/bad.yaml +12 -0
  101. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-agent-id/workspace.yaml +5 -0
  102. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-archetype-id/archetypes/first.yaml +11 -0
  103. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-archetype-id/archetypes/second.yaml +11 -0
  104. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-archetype-id/workspace.yaml +5 -0
  105. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-skill-id/skills/one.yaml +14 -0
  106. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-skill-id/skills/two.yaml +14 -0
  107. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/duplicate-skill-id/workspace.yaml +5 -0
  108. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/kind-mismatch/skills/wrong-kind.yaml +11 -0
  109. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/kind-mismatch/workspace.yaml +5 -0
  110. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/missing-workspace-yaml/topologies/hello.yaml +11 -0
  111. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/trigger-unknown-target/triggers/orphan.yaml +8 -0
  112. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/trigger-unknown-target/workspace.yaml +5 -0
  113. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/unknown-archetype/topologies/bad.yaml +10 -0
  114. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/unknown-archetype/workspace.yaml +5 -0
  115. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/yaml-parse-error/topologies/broken.yaml +6 -0
  116. swarmkit_runtime-1.0.0/tests/fixtures/workspaces-invalid/yaml-parse-error/workspace.yaml +5 -0
  117. swarmkit_runtime-1.0.0/tests/test_agt_governance.py +231 -0
  118. swarmkit_runtime-1.0.0/tests/test_cli_stubs.py +32 -0
  119. swarmkit_runtime-1.0.0/tests/test_code_review_swarm.py +109 -0
  120. swarmkit_runtime-1.0.0/tests/test_compiler.py +514 -0
  121. swarmkit_runtime-1.0.0/tests/test_github_mcp_skills.py +84 -0
  122. swarmkit_runtime-1.0.0/tests/test_governance_provider.py +234 -0
  123. swarmkit_runtime-1.0.0/tests/test_governance_selection.py +89 -0
  124. swarmkit_runtime-1.0.0/tests/test_hello_swarm_example.py +52 -0
  125. swarmkit_runtime-1.0.0/tests/test_knowledge_pack.py +189 -0
  126. swarmkit_runtime-1.0.0/tests/test_knowledge_server.py +272 -0
  127. swarmkit_runtime-1.0.0/tests/test_mcp_client.py +193 -0
  128. swarmkit_runtime-1.0.0/tests/test_model_providers.py +318 -0
  129. swarmkit_runtime-1.0.0/tests/test_output_validator.py +185 -0
  130. swarmkit_runtime-1.0.0/tests/test_panel.py +83 -0
  131. swarmkit_runtime-1.0.0/tests/test_registries.py +140 -0
  132. swarmkit_runtime-1.0.0/tests/test_resolver.py +153 -0
  133. swarmkit_runtime-1.0.0/tests/test_review_queue.py +96 -0
  134. swarmkit_runtime-1.0.0/tests/test_run_cli.py +75 -0
  135. swarmkit_runtime-1.0.0/tests/test_server.py +117 -0
  136. swarmkit_runtime-1.0.0/tests/test_skill_authoring_swarm.py +123 -0
  137. swarmkit_runtime-1.0.0/tests/test_skill_executor.py +114 -0
  138. swarmkit_runtime-1.0.0/tests/test_skill_gap_log.py +89 -0
  139. swarmkit_runtime-1.0.0/tests/test_smoke.py +21 -0
  140. swarmkit_runtime-1.0.0/tests/test_validate_cli.py +204 -0
  141. swarmkit_runtime-1.0.0/tests/test_validation.py +271 -0
  142. swarmkit_runtime-1.0.0/tests/test_workspace_discovery.py +189 -0
@@ -0,0 +1,66 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ .venv/
8
+ venv/
9
+ env/
10
+ .eggs/
11
+ *.egg-info/
12
+ *.egg
13
+ build/
14
+ dist/
15
+ .pytest_cache/
16
+ .mypy_cache/
17
+ .ruff_cache/
18
+ .pyre/
19
+ .pytype/
20
+ .coverage
21
+ .coverage.*
22
+ htmlcov/
23
+ coverage.xml
24
+ *.cover
25
+ .hypothesis/
26
+ .tox/
27
+ .nox/
28
+
29
+ # Node / TypeScript
30
+ node_modules/
31
+ .next/
32
+ out/
33
+ .turbo/
34
+ .nx/
35
+ dist/
36
+ *.tsbuildinfo
37
+ .pnpm-store/
38
+ .yarn/
39
+
40
+ # Editors / OS
41
+ .vscode/
42
+ .idea/
43
+ *.swp
44
+ *.swo
45
+ .DS_Store
46
+ Thumbs.db
47
+ *~
48
+
49
+ # Env / secrets
50
+ .env
51
+ .env.local
52
+ .env.*.local
53
+ *.pem
54
+
55
+ # SwarmKit runtime artifacts (per design §9.3)
56
+ .swarmkit/
57
+ *.sqlite
58
+ *.sqlite-journal
59
+
60
+ # Claude Code
61
+ .claude/settings.local.json
62
+
63
+ # Build / logs
64
+ *.log
65
+ .cache/
66
+ _site/
@@ -0,0 +1,55 @@
1
+ # CLAUDE.md — packages/runtime
2
+
3
+ ## Package identity
4
+
5
+ `swarmkit-runtime` — the Python component of the three-package system. Loads topology files, compiles them into LangGraph graphs, enforces governance through the `GovernanceProvider` abstraction, and exposes the `swarmkit` CLI + FastAPI server.
6
+
7
+ The design doc is the authoritative source for architectural decisions — see `design/SwarmKit-Design-v0.6.md`. §9, §14, §16, §18 are the most relevant sections to this package.
8
+
9
+ ## Module map
10
+
11
+ | Module | Responsibility | Design ref |
12
+ | --- | --- | --- |
13
+ | `cli/` | Typer-based CLI, authoring entry points | §14.2 |
14
+ | `topology/` | Load, validate, resolve topology YAML/JSON | §10 |
15
+ | `skills/` | Skill registry + category semantics (capability, decision, coordination, persistence) | §6 |
16
+ | `archetypes/` | Archetype registry and instantiation | §13 |
17
+ | `governance/` | `GovernanceProvider` interface + `AGTGovernanceProvider` | §8.5, §16.5 |
18
+ | `langgraph_compiler/` | Topology → `StateGraph` dynamic construction | §14.3 |
19
+ | `mcp/` | MCP client + sandboxed server lifecycle | §18 |
20
+ | `audit/` | Append-only audit log, skill gap log surfacing | §14.5, §16.4 |
21
+
22
+ ## Non-negotiable invariants
23
+
24
+ These come from the design's architectural principles and separation-of-powers model. Do not relax without explicit approval.
25
+
26
+ 1. **Topology is data.** Never generate or inline topology as Python code inside this package. The runtime reads YAML/JSON and interprets.
27
+ 2. **All governance goes through `GovernanceProvider`.** No direct AGT imports outside `governance/`. If code needs policy evaluation, identity, or audit, it goes through the interface.
28
+ 3. **Audit is append-only from agent perspective.** No code path should expose `update` or `delete` on audit entries to executive-layer callers.
29
+ 4. **Pillar boundaries are enforced at the module level** (design §8.4). Executive code invokes skills via middleware that routes through the policy engine — there is no bypass.
30
+ 5. **Skills are the only extension primitive.** When adding a capability, add a skill category or skill definition — do not introduce parallel extension mechanisms.
31
+ 6. **Eject must stay intact.** Every feature you add to the runtime needs an ejection story; if it cannot be expressed in generated LangGraph code, reconsider the design.
32
+
33
+ ## Style
34
+
35
+ - Python 3.11+, strict typing (`mypy --strict`).
36
+ - Prefer `pydantic` models for all schema-shaped data; use `dataclass` only for internal value objects.
37
+ - Async-first where I/O is involved (`anyio` / `httpx` / `fastapi`).
38
+ - Error taxonomy: custom exceptions live in each module's `_errors.py`; no bare `raise Exception`.
39
+
40
+ ## Testing
41
+
42
+ - `pytest` + `pytest-asyncio`. Tests live under `tests/`.
43
+ - Integration tests that touch real MCP servers or AGT gate on env vars; unit tests mock at the `GovernanceProvider` seam.
44
+ - Every reference topology ships a smoke test that loads + compiles it without executing.
45
+
46
+ ## Commands
47
+
48
+ ```bash
49
+ uv run pytest packages/runtime/tests # tests
50
+ uv run ruff check packages/runtime # lint
51
+ uv run mypy packages/runtime # typecheck
52
+ uv run swarmkit --help # CLI entry
53
+ ```
54
+
55
+ Or via the root justfile: `just test-py`, `just lint-py`, `just typecheck-py`.
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: swarmkit-runtime
3
+ Version: 1.0.0
4
+ Summary: SwarmKit runtime: topology interpreter, LangGraph compiler, AGT-backed governance, CLI and HTTP server.
5
+ Author: Srijith Kartha
6
+ License: MIT
7
+ Keywords: agents,agt,langgraph,mcp,multi-agent,swarm
8
+ Classifier: Development Status :: 2 - Pre-Alpha
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: agent-os-kernel<4.0,>=3.2.0
17
+ Requires-Dist: agent-sre<4.0,>=3.2.0
18
+ Requires-Dist: agentmesh-platform<4.0,>=3.2.0
19
+ Requires-Dist: anthropic>=0.39
20
+ Requires-Dist: anyio>=4.4
21
+ Requires-Dist: fastapi>=0.115
22
+ Requires-Dist: google-genai>=1.0
23
+ Requires-Dist: httpx>=0.27
24
+ Requires-Dist: langchain-core>=0.3
25
+ Requires-Dist: langgraph>=0.2
26
+ Requires-Dist: mcp>=1.0
27
+ Requires-Dist: openai>=1.50
28
+ Requires-Dist: pydantic>=2.8
29
+ Requires-Dist: pyyaml>=6.0
30
+ Requires-Dist: rich>=13.7
31
+ Requires-Dist: sqlalchemy>=2.0
32
+ Requires-Dist: swarmkit-schema
33
+ Requires-Dist: typer>=0.12
34
+ Requires-Dist: uvicorn[standard]>=0.30
35
+ Provides-Extra: dev
36
+ Requires-Dist: mypy>=1.11; extra == 'dev'
37
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
38
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
39
+ Requires-Dist: pytest>=8.0; extra == 'dev'
40
+ Requires-Dist: ruff>=0.6; extra == 'dev'
41
+ Requires-Dist: types-pyyaml; extra == 'dev'
42
+ Description-Content-Type: text/markdown
43
+
44
+ # swarmkit-runtime
45
+
46
+ Python runtime for SwarmKit. Interprets topology files, compiles them into LangGraph `StateGraph`s, enforces governance via the `GovernanceProvider` abstraction (AGT-backed in v1.0), and exposes the `swarmkit` CLI plus a persistent HTTP server.
47
+
48
+ ## Layout
49
+
50
+ ```
51
+ src/swarmkit_runtime/
52
+ ├── cli/ # Typer-based CLI: init, author, run, serve, eject
53
+ ├── topology/ # Topology loader, validator, resolver (archetype + skill refs)
54
+ ├── skills/ # Skill registry, category-specific semantics, composition
55
+ ├── archetypes/ # Archetype registry and instantiation
56
+ ├── governance/ # GovernanceProvider interface + AGTGovernanceProvider impl
57
+ ├── langgraph_compiler/ # Topology → StateGraph compilation (design §14.3)
58
+ ├── mcp/ # MCP client, server lifecycle, sandbox supervision
59
+ └── audit/ # Append-only audit log adapters, skill gap log surfacing
60
+ ```
61
+
62
+ ## Design references
63
+
64
+ - §7 Architectural Principles — `topology as data`, `eject, never lock-in`
65
+ - §8 Separation of Powers — `governance/` module is the SwarmKit side; AGT is the implementation
66
+ - §9 System Architecture — this package is component #1 of 3
67
+ - §14 Runtime Architecture — three execution modes (one-shot, persistent, scheduled)
68
+
69
+ ## Entry points (design §14.2)
70
+
71
+ | Command | What it does |
72
+ | --- | --- |
73
+ | `swarmkit init` | Launch Workspace Authoring Swarm in terminal chat mode |
74
+ | `swarmkit author topology [name]` | Launch Topology Authoring variant |
75
+ | `swarmkit author skill [name]` | Launch Skill Authoring Swarm |
76
+ | `swarmkit author archetype [name]` | Launch Archetype Authoring variant |
77
+ | `swarmkit run topology.yaml` | One-shot execution |
78
+ | `swarmkit serve workspace/` | Persistent / scheduled mode |
79
+ | `swarmkit eject topology.yaml` | Export LangGraph code |
80
+
81
+ ## Development
82
+
83
+ ```bash
84
+ uv sync --package swarmkit-runtime
85
+ uv run pytest packages/runtime/tests
86
+ uv run swarmkit --help
87
+ ```
@@ -0,0 +1,44 @@
1
+ # swarmkit-runtime
2
+
3
+ Python runtime for SwarmKit. Interprets topology files, compiles them into LangGraph `StateGraph`s, enforces governance via the `GovernanceProvider` abstraction (AGT-backed in v1.0), and exposes the `swarmkit` CLI plus a persistent HTTP server.
4
+
5
+ ## Layout
6
+
7
+ ```
8
+ src/swarmkit_runtime/
9
+ ├── cli/ # Typer-based CLI: init, author, run, serve, eject
10
+ ├── topology/ # Topology loader, validator, resolver (archetype + skill refs)
11
+ ├── skills/ # Skill registry, category-specific semantics, composition
12
+ ├── archetypes/ # Archetype registry and instantiation
13
+ ├── governance/ # GovernanceProvider interface + AGTGovernanceProvider impl
14
+ ├── langgraph_compiler/ # Topology → StateGraph compilation (design §14.3)
15
+ ├── mcp/ # MCP client, server lifecycle, sandbox supervision
16
+ └── audit/ # Append-only audit log adapters, skill gap log surfacing
17
+ ```
18
+
19
+ ## Design references
20
+
21
+ - §7 Architectural Principles — `topology as data`, `eject, never lock-in`
22
+ - §8 Separation of Powers — `governance/` module is the SwarmKit side; AGT is the implementation
23
+ - §9 System Architecture — this package is component #1 of 3
24
+ - §14 Runtime Architecture — three execution modes (one-shot, persistent, scheduled)
25
+
26
+ ## Entry points (design §14.2)
27
+
28
+ | Command | What it does |
29
+ | --- | --- |
30
+ | `swarmkit init` | Launch Workspace Authoring Swarm in terminal chat mode |
31
+ | `swarmkit author topology [name]` | Launch Topology Authoring variant |
32
+ | `swarmkit author skill [name]` | Launch Skill Authoring Swarm |
33
+ | `swarmkit author archetype [name]` | Launch Archetype Authoring variant |
34
+ | `swarmkit run topology.yaml` | One-shot execution |
35
+ | `swarmkit serve workspace/` | Persistent / scheduled mode |
36
+ | `swarmkit eject topology.yaml` | Export LangGraph code |
37
+
38
+ ## Development
39
+
40
+ ```bash
41
+ uv sync --package swarmkit-runtime
42
+ uv run pytest packages/runtime/tests
43
+ uv run swarmkit --help
44
+ ```
@@ -0,0 +1,82 @@
1
+ [project]
2
+ name = "swarmkit-runtime"
3
+ version = "1.0.0"
4
+ description = "SwarmKit runtime: topology interpreter, LangGraph compiler, AGT-backed governance, CLI and HTTP server."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "Srijith Kartha" }]
9
+ keywords = ["agents", "multi-agent", "swarm", "langgraph", "mcp", "agt"]
10
+ classifiers = [
11
+ "Development Status :: 2 - Pre-Alpha",
12
+ "License :: OSI Approved :: MIT License",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.11",
15
+ "Programming Language :: Python :: 3.12",
16
+ "Programming Language :: Python :: 3.13",
17
+ "Topic :: Software Development :: Libraries :: Python Modules",
18
+ ]
19
+
20
+ # Dependencies below are intentionally un-pinned placeholders. Lock concrete
21
+ # versions once Phase 1 implementation begins — see design §20.1.
22
+ dependencies = [
23
+ # Core
24
+ "pydantic>=2.8",
25
+ "pyyaml>=6.0",
26
+ "typer>=0.12", # CLI — `swarmkit` entrypoint
27
+ "rich>=13.7", # terminal rendering for authoring chat
28
+ "httpx>=0.27",
29
+ "anyio>=4.4",
30
+
31
+ # Execution engine (design §7, §14)
32
+ "langgraph>=0.2",
33
+ "langchain-core>=0.3",
34
+
35
+ # Governance — Microsoft AGT (design §8, §16).
36
+ # Pinned to 3.x; AGT is iterating fast (public preview, v1→v3 in 7 weeks).
37
+ # The GovernanceProvider ABC (§8.5) isolates the runtime from AGT API churn.
38
+ "agent-os-kernel>=3.2.0,<4.0",
39
+ "agentmesh-platform>=3.2.0,<4.0",
40
+ "agent-sre>=3.2.0,<4.0",
41
+
42
+ # MCP (design §18)
43
+ "mcp>=1.0",
44
+
45
+ # LLM SDKs — one per ModelProvider built-in (design/details/model-provider-abstraction.md).
46
+ # Only model_providers/ imports these; everything else goes through ModelProvider ABC.
47
+ "anthropic>=0.39",
48
+ "google-genai>=1.0",
49
+ "openai>=1.50",
50
+ # Ollama uses httpx only (already in core deps) — no dedicated SDK.
51
+
52
+ # HTTP server for persistent mode (design §14.1)
53
+ "fastapi>=0.115",
54
+ "uvicorn[standard]>=0.30",
55
+
56
+ # Storage / checkpointing (design §14.5)
57
+ "sqlalchemy>=2.0",
58
+ # "psycopg[binary]>=3.2", # optional Postgres backend
59
+
60
+ # Schema package (workspace sibling)
61
+ "swarmkit-schema",
62
+ ]
63
+
64
+ [project.optional-dependencies]
65
+ dev = [
66
+ "pytest>=8.0",
67
+ "pytest-asyncio>=0.23",
68
+ "pytest-cov>=5.0",
69
+ "mypy>=1.11",
70
+ "ruff>=0.6",
71
+ "types-pyyaml",
72
+ ]
73
+
74
+ [project.scripts]
75
+ swarmkit = "swarmkit_runtime.cli:app"
76
+
77
+ [build-system]
78
+ requires = ["hatchling"]
79
+ build-backend = "hatchling.build"
80
+
81
+ [tool.hatch.build.targets.wheel]
82
+ packages = ["src/swarmkit_runtime"]
@@ -0,0 +1,6 @@
1
+ """SwarmKit runtime — topology interpreter, LangGraph compiler, governance wiring.
2
+
3
+ See `design/SwarmKit-Design-v0.6.md` §9 and §14 for architectural context.
4
+ """
5
+
6
+ __version__ = "0.0.1"
@@ -0,0 +1,308 @@
1
+ """WorkspaceRuntime — the backend that CLI, HTTP server, and web UI call into.
2
+
3
+ Owns the full execution lifecycle: resolve workspace → build providers →
4
+ build governance → wire MCP → compile topology → invoke graph → close.
5
+ The CLI is a thin interface over this; ``swarmkit serve`` (M9) and the
6
+ v1.1 web UI will be additional interfaces over the same class.
7
+
8
+ See ``design/details/workspace-runtime.md`` (to be written) and the
9
+ architectural decision in ``memory/feedback_cli_architecture.md``.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import os
15
+ import sys
16
+ from dataclasses import dataclass, field
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ from langgraph.graph.state import CompiledStateGraph
21
+
22
+ from swarmkit_runtime.governance import GovernanceProvider
23
+ from swarmkit_runtime.governance._mock import MockGovernanceProvider
24
+ from swarmkit_runtime.langgraph_compiler import compile_topology
25
+ from swarmkit_runtime.mcp import MCPClientManager, MCPServerConfig, parse_mcp_servers
26
+ from swarmkit_runtime.model_providers import (
27
+ AnthropicModelProvider,
28
+ GoogleModelProvider,
29
+ GroqModelProvider,
30
+ MockModelProvider,
31
+ OllamaModelProvider,
32
+ OpenAIModelProvider,
33
+ OpenRouterModelProvider,
34
+ ProviderRegistry,
35
+ TogetherModelProvider,
36
+ )
37
+ from swarmkit_runtime.model_providers._registry import ModelProviderProtocol
38
+ from swarmkit_runtime.resolver import ResolvedWorkspace, resolve_workspace
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class RunResult:
43
+ """Output of a topology execution."""
44
+
45
+ output: str
46
+ agent_results: dict[str, str] = field(default_factory=dict)
47
+
48
+
49
+ class MissingMCPServerError(Exception):
50
+ """A skill targets an MCP server that the workspace doesn't declare."""
51
+
52
+ def __init__(self, missing: list[tuple[str, str]]) -> None:
53
+ self.missing = missing
54
+ lines = [
55
+ f"skill '{sid}' targets MCP server '{srv}' but the workspace declares no such server"
56
+ for sid, srv in missing
57
+ ]
58
+ super().__init__("\n".join(lines))
59
+
60
+
61
+ class WorkspaceRuntime:
62
+ """The backend that both CLI and HTTP server call into.
63
+
64
+ Holds a resolved workspace plus all the wired runtime components
65
+ (model providers, governance, MCP manager). Constructed via the
66
+ ``from_workspace_path`` classmethod.
67
+ """
68
+
69
+ def __init__(
70
+ self,
71
+ *,
72
+ workspace: ResolvedWorkspace,
73
+ workspace_root: Path,
74
+ provider_registry: ProviderRegistry,
75
+ governance: GovernanceProvider,
76
+ mcp_manager: MCPClientManager | None,
77
+ ) -> None:
78
+ self._workspace = workspace
79
+ self._workspace_root = workspace_root
80
+ self._provider_registry = provider_registry
81
+ self._governance = governance
82
+ self._mcp_manager = mcp_manager
83
+
84
+ @classmethod
85
+ def from_workspace_path(cls, path: Path) -> WorkspaceRuntime:
86
+ """Build a fully-wired runtime from a workspace directory.
87
+
88
+ Resolves the workspace, registers model providers, selects the
89
+ governance provider, parses MCP server config, and validates
90
+ that every mcp_tool skill targets a configured server.
91
+
92
+ Raises ``ResolutionErrors`` if the workspace is invalid, or
93
+ ``MissingMCPServerError`` if skills reference unconfigured
94
+ MCP servers.
95
+ """
96
+ ws_root = path.resolve()
97
+ workspace = resolve_workspace(ws_root)
98
+
99
+ registry = ProviderRegistry()
100
+ register_available_providers(registry)
101
+
102
+ governance = build_governance(workspace, ws_root)
103
+
104
+ mcp_configs = parse_mcp_servers(getattr(workspace.raw, "mcp_servers", None))
105
+ mcp_manager = MCPClientManager(mcp_configs, workspace_root=ws_root) if mcp_configs else None
106
+
107
+ missing = find_missing_mcp_servers(workspace, mcp_configs)
108
+ if missing:
109
+ raise MissingMCPServerError(missing)
110
+
111
+ return cls(
112
+ workspace=workspace,
113
+ workspace_root=ws_root,
114
+ provider_registry=registry,
115
+ governance=governance,
116
+ mcp_manager=mcp_manager,
117
+ )
118
+
119
+ def compile(self, topology_name: str) -> CompiledStateGraph[Any]:
120
+ """Compile a named topology into a LangGraph graph.
121
+
122
+ Raises ``KeyError`` if the topology doesn't exist.
123
+ """
124
+ if topology_name not in self._workspace.topologies:
125
+ available = sorted(self._workspace.topologies.keys())
126
+ raise KeyError(
127
+ f"Topology '{topology_name}' not found. "
128
+ f"Available: {', '.join(available) or '(none)'}."
129
+ )
130
+
131
+ topology = self._workspace.topologies[topology_name]
132
+ return compile_topology(
133
+ topology,
134
+ provider_registry=self._provider_registry,
135
+ governance=self._governance,
136
+ mcp_manager=self._mcp_manager,
137
+ )
138
+
139
+ async def run(
140
+ self,
141
+ topology_name: str,
142
+ user_input: str,
143
+ *,
144
+ max_steps: int = 10,
145
+ ) -> RunResult:
146
+ """Execute a topology end-to-end and return the result.
147
+
148
+ Handles MCP session lifecycle (start_all / close_all) within
149
+ the same async task so the SDK's anyio task groups unwind cleanly.
150
+ """
151
+ graph = self.compile(topology_name)
152
+
153
+ if self._mcp_manager is not None:
154
+ await self._mcp_manager.start_all()
155
+ try:
156
+ result = await graph.ainvoke(
157
+ {
158
+ "input": user_input,
159
+ "messages": [],
160
+ "agent_results": {},
161
+ "current_agent": "",
162
+ "output": "",
163
+ },
164
+ config={"recursion_limit": max_steps},
165
+ )
166
+ finally:
167
+ if self._mcp_manager is not None:
168
+ await self._mcp_manager.close_all()
169
+
170
+ return RunResult(
171
+ output=result.get("output", ""),
172
+ agent_results={
173
+ k: str(v) for k, v in result.get("agent_results", {}).items() if isinstance(v, str)
174
+ },
175
+ )
176
+
177
+ async def close(self) -> None:
178
+ """Release all held resources."""
179
+ if self._mcp_manager is not None:
180
+ await self._mcp_manager.close_all()
181
+
182
+ @property
183
+ def workspace(self) -> ResolvedWorkspace:
184
+ return self._workspace
185
+
186
+ @property
187
+ def workspace_root(self) -> Path:
188
+ return self._workspace_root
189
+
190
+ @property
191
+ def governance(self) -> GovernanceProvider:
192
+ return self._governance
193
+
194
+ @property
195
+ def mcp_manager(self) -> MCPClientManager | None:
196
+ return self._mcp_manager
197
+
198
+ @property
199
+ def provider_registry(self) -> ProviderRegistry:
200
+ return self._provider_registry
201
+
202
+
203
+ # ---- helpers (public — used by CLI and tests) ----------------------------
204
+
205
+
206
+ def register_available_providers(registry: ProviderRegistry) -> None:
207
+ """Register all model providers whose credentials are in the environment."""
208
+ registry.register(MockModelProvider())
209
+
210
+ if os.environ.get("ANTHROPIC_API_KEY"):
211
+ registry.register(AnthropicModelProvider())
212
+ if os.environ.get("GOOGLE_API_KEY"):
213
+ registry.register(GoogleModelProvider())
214
+ if os.environ.get("OPENAI_API_KEY"):
215
+ registry.register(OpenAIModelProvider())
216
+ if os.environ.get("OPENROUTER_API_KEY"):
217
+ registry.register(OpenRouterModelProvider())
218
+ if os.environ.get("GROQ_API_KEY"):
219
+ registry.register(GroqModelProvider())
220
+ if os.environ.get("TOGETHER_API_KEY"):
221
+ registry.register(TogetherModelProvider())
222
+
223
+ registry.register(OllamaModelProvider())
224
+
225
+
226
+ def build_governance(workspace: ResolvedWorkspace, ws_root: Path) -> GovernanceProvider:
227
+ """Select the GovernanceProvider based on workspace.yaml's governance block."""
228
+ gov = getattr(workspace.raw, "governance", None)
229
+ if gov is None:
230
+ return MockGovernanceProvider(allow_all=True)
231
+
232
+ provider_value = gov.provider.value if hasattr(gov.provider, "value") else str(gov.provider)
233
+
234
+ if provider_value == "agt":
235
+ from swarmkit_runtime.governance.agt_provider import AGTGovernanceProvider # noqa: PLC0415
236
+
237
+ config = gov.config or {}
238
+ policies_dir = ws_root / config.get("policies_dir", "policies")
239
+ audit_db = ws_root / ".swarmkit" / "audit.db"
240
+ audit_db.parent.mkdir(parents=True, exist_ok=True)
241
+ return AGTGovernanceProvider.from_config(
242
+ policy_dir=policies_dir,
243
+ audit_db=audit_db,
244
+ )
245
+
246
+ if provider_value == "custom":
247
+ print(
248
+ "warning: governance.provider=custom is not yet supported; "
249
+ "falling back to mock. See design §8.5 for the plugin path.",
250
+ file=sys.stderr,
251
+ )
252
+
253
+ return MockGovernanceProvider(allow_all=True)
254
+
255
+
256
+ def resolve_authoring_provider(
257
+ registry: ProviderRegistry | None = None,
258
+ ) -> tuple[ModelProviderProtocol, str]:
259
+ """Resolve which model provider + model name to use for authoring.
260
+
261
+ Checks SWARMKIT_AUTHOR_MODEL (format: provider/model), then falls
262
+ back to SWARMKIT_PROVIDER + SWARMKIT_MODEL, then first available
263
+ real provider.
264
+ """
265
+ author_model = os.environ.get("SWARMKIT_AUTHOR_MODEL", "")
266
+ if "/" in author_model:
267
+ provider_id, model_name = author_model.split("/", 1)
268
+ else:
269
+ provider_id = os.environ.get("SWARMKIT_PROVIDER", "")
270
+ model_name = os.environ.get("SWARMKIT_MODEL", "")
271
+
272
+ if registry is None:
273
+ registry = ProviderRegistry()
274
+ register_available_providers(registry)
275
+
276
+ if provider_id:
277
+ provider = registry.get(provider_id)
278
+ if provider is not None:
279
+ return provider, model_name or "claude-sonnet-4-6"
280
+
281
+ for pid in registry.provider_ids:
282
+ if pid == "mock":
283
+ continue
284
+ provider = registry.get(pid)
285
+ if provider is not None:
286
+ return provider, model_name or "claude-sonnet-4-6"
287
+
288
+ raise RuntimeError(
289
+ "No model provider available. Set SWARMKIT_PROVIDER "
290
+ "and the corresponding API key (e.g. GROQ_API_KEY)."
291
+ )
292
+
293
+
294
+ def find_missing_mcp_servers(
295
+ workspace: ResolvedWorkspace,
296
+ mcp_configs: dict[str, MCPServerConfig],
297
+ ) -> list[tuple[str, str]]:
298
+ """Return ``(skill_id, server_id)`` pairs whose mcp_tool target is unconfigured."""
299
+ missing: list[tuple[str, str]] = []
300
+ for skill_id, skill in workspace.skills.items():
301
+ impl = skill.raw.implementation
302
+ impl_type = impl.get("type") if isinstance(impl, dict) else getattr(impl, "type", None)
303
+ if impl_type != "mcp_tool":
304
+ continue
305
+ server_id = impl.get("server") if isinstance(impl, dict) else getattr(impl, "server", "")
306
+ if server_id and server_id not in mcp_configs:
307
+ missing.append((skill_id, server_id))
308
+ return missing