roboshed 0.1.1.dev1__tar.gz → 0.1.1.dev2__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 (95) hide show
  1. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/CHANGELOG.md +14 -0
  2. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/PKG-INFO +48 -38
  3. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/README.md +46 -36
  4. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/pyproject.toml +2 -2
  5. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/agents/librarian.py +14 -9
  6. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/agents/orchestrator.py +9 -7
  7. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/capabilities.py +112 -56
  8. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/dependency_health.py +3 -4
  9. roboshed-0.1.1.dev2/src/roboshed/deployments/__init__.py +5 -0
  10. roboshed-0.1.1.dev2/src/roboshed/deployments/robosprawl.py +128 -0
  11. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/memory/test_librarian.py +66 -72
  12. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_agent_deployment.py +83 -76
  13. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_agent_presets.py +16 -12
  14. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_capabilities.py +20 -17
  15. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_dependency_inspection.py +5 -5
  16. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_deployment_graph.py +50 -39
  17. roboshed-0.1.1.dev2/tests/test_robosprawl.py +233 -0
  18. roboshed-0.1.1.dev1/src/roboshed/deployments/__init__.py +0 -60
  19. roboshed-0.1.1.dev1/src/roboshed/deployments/robosprawl.py +0 -84
  20. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/.gitignore +0 -0
  21. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/LICENSE +0 -0
  22. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/__init__.py +0 -0
  23. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/agents/__init__.py +0 -0
  24. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/identifiers.py +0 -0
  25. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/models.py +0 -0
  26. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/py.typed +0 -0
  27. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/sandbox.py +0 -0
  28. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/__init__.py +0 -0
  29. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/cli_tools/__init__.py +0 -0
  30. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/cli_tools/prompts.py +0 -0
  31. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/email_tools/__init__.py +0 -0
  32. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/email_tools/prompts.py +0 -0
  33. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/file_editing/__init__.py +0 -0
  34. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/file_editing/prompts.py +0 -0
  35. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/skills/robosprawl.py +0 -0
  36. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/__init__.py +0 -0
  37. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/_snapshot_metadata.py +0 -0
  38. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/apply_patch.py +0 -0
  39. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/__init__.py +0 -0
  40. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/run_file_command/__init__.py +0 -0
  41. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/run_file_command/command.py +0 -0
  42. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/run_file_command/resolve.py +0 -0
  43. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/run_file_command/specs.py +0 -0
  44. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/utilities/__init__.py +0 -0
  45. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/utilities/cmd_spec.py +0 -0
  46. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/utilities/constants.py +0 -0
  47. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/utilities/formatting.py +0 -0
  48. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/cli_commands/utilities/path_extractors.py +0 -0
  49. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/compactification/__init__.py +0 -0
  50. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/compactification/compactify_messages.py +0 -0
  51. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/compactification/prompts.py +0 -0
  52. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/compactification/summarize.py +0 -0
  53. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/compactification/summary_prompts.py +0 -0
  54. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/consolidate_memory.py +0 -0
  55. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/consolidate_memory_example.py +0 -0
  56. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/consolidate_memory_prompts.py +0 -0
  57. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/__init__.py +0 -0
  58. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/contracts.py +0 -0
  59. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/drafts.py +0 -0
  60. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/factory.py +0 -0
  61. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/inputs.py +0 -0
  62. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/messages.py +0 -0
  63. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/email/runtime.py +0 -0
  64. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/guard.py +0 -0
  65. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/guard_formatting.py +0 -0
  66. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/librarian_errors.py +0 -0
  67. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/memory_files.py +0 -0
  68. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/purge_files.py +0 -0
  69. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/runner.py +0 -0
  70. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/sleep_between_runs.py +0 -0
  71. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/snapshot_conversation_example.py +0 -0
  72. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/snapshot_conversation_prompts.py +0 -0
  73. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/snapshot_conversations.py +0 -0
  74. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/snapshot_normalize.py +0 -0
  75. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/truncation.py +0 -0
  76. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/types.py +0 -0
  77. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/src/roboshed/tools/utils.py +0 -0
  78. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/memory/test_consolidate_memory.py +0 -0
  79. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/memory/test_memory_prompts.py +0 -0
  80. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/memory/test_purge_files.py +0 -0
  81. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/memory/test_snapshot_conversations.py +0 -0
  82. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/memory/test_summarize_conversation.py +0 -0
  83. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_apply_patch.py +0 -0
  84. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_build_guarded_tool_chain.py +0 -0
  85. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_cli_command_chaining.py +0 -0
  86. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_cli_command_utils.py +0 -0
  87. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_cli_tools_prompt_examples.py +0 -0
  88. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_compactify_messages.py +0 -0
  89. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_compaction_runtime.py +0 -0
  90. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_dependency_health.py +0 -0
  91. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_email_factory.py +0 -0
  92. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_generic_guards.py +0 -0
  93. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_guard.py +0 -0
  94. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_path_extractors.py +0 -0
  95. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev2}/tests/test_sandbox.py +0 -0
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.1.1.dev2 - 2026-09-12
6
+
7
+ - Breaking: move permission, sandbox, watched-agent, and default model inputs
8
+ from Shed capability objects to their owning `DeployableAgent` configuration.
9
+ Capability-specific thresholds, limits, timeouts, and endpoint overrides stay
10
+ on the capability objects.
11
+ - Breaking: remove `Deployment` and replace the callable `RoboSprawl` dataclass
12
+ with a standalone configuration class. Construct `RoboSprawl()` without
13
+ inputs, supply runtime inputs through its setters, then call argument-free
14
+ `build()` to obtain fresh root/background agents. `robosprawl` aliases the
15
+ class, not the former function signature. The existing orchestrator defaults,
16
+ Librarian pipeline, project context, and persistence remain in the recipe.
17
+ Use one configuration instance per new run; see `docs/agent-factories.md`.
18
+
5
19
  ## 0.1.1.dev1 - 2026-09-12
6
20
 
7
21
  - Add `roboshed.deployments.robosprawl.RoboSprawl`, a callable configuration
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: roboshed
3
- Version: 0.1.1.dev1
3
+ Version: 0.1.1.dev2
4
4
  Import-Name: roboshed
5
5
  Summary: roboshed: optional building blocks for Roboz
6
6
  Project-URL: Repository, https://github.com/Tachion-Oy/roboz
@@ -11,7 +11,7 @@ Classifier: Development Status :: 2 - Pre-Alpha
11
11
  Classifier: Typing :: Typed
12
12
  Requires-Python: >=3.13
13
13
  Requires-Dist: pydantic>=2.12.4
14
- Requires-Dist: roboz<0.2.0,>=0.1.2.dev3
14
+ Requires-Dist: roboz<0.2.0,>=0.1.2.dev4
15
15
  Description-Content-Type: text/markdown
16
16
 
17
17
  # roboshed
@@ -35,48 +35,59 @@ permissions = PermissionPolicy.local(Path("./sandbox"))
35
35
  agent = DeployableAgent(
36
36
  name="file_worker",
37
37
  system_prompt="Complete the user's task, then call stop.",
38
- agent_endpoint=MockLLMEndpoint([
39
- {"action": "stop", "rationale": "done", "value": "Ready."}
40
- ]),
41
- capabilities=(
38
+ default_capabilities=(
42
39
  Capability(tools=(stop,)),
43
- FileCommands(permissions),
44
- FileEditing(permissions),
40
+ FileCommands(),
41
+ FileEditing(),
45
42
  ),
46
- ).build()
43
+ )
44
+ agent.set_agent_endpoint(MockLLMEndpoint([
45
+ {"action": "stop", "rationale": "done", "value": "Ready."}
46
+ ]))
47
+ agent.set_attributes(permissions=permissions)
48
+ agent, background_agents = agent.build()
47
49
  result, messages = agent.invoke()
48
50
  ```
49
51
 
50
52
  `roboshed.capabilities` provides `FileCommands`, `FileEditing`, `Compactification`,
51
53
  `ConversationSnapshots`, `MemoryConsolidation`, `ArtifactRetention`, and
52
54
  `MaintenanceCadence`, alongside the `tools` and `skills` modules. Applications
53
- choose capabilities through each agent definition's `capabilities` tuple.
55
+ choose fixed capabilities through `default_capabilities` and append application
56
+ extensions with `add_capabilities()`.
54
57
  A capability owns its tools and skills. Generic `DeployableAgent` definitions
55
58
  live in `roboz.deployment`.
56
59
  Reusable `orchestrator` and `librarian` constructors live in `roboshed.agents`.
57
60
  The orchestrator owns stop and guarded file work, and the Librarian owns
58
61
  snapshots, consolidation, retention, and cadence. Root-only application
59
- capabilities go in `Deployment.additional_capabilities`, after the agent's
60
- built-in capability loop, without unpacking the role defaults.
62
+ capabilities append after the agent's protected defaults, without unpacking the
63
+ role definitions.
61
64
 
62
- Each capability uses an explicit endpoint override or its agent's default.
63
- Runtime controls remain separate. Direct standalone builds accept explicit
64
- `PermissionPolicy` and sandbox inputs.
65
+ Each capability declares the typed attributes it reads from its owning
66
+ `DeployableAgent`. Runtime controls remain separate. Use `set_attributes()` to
67
+ supply standalone permission policies and sandbox inputs before building.
65
68
 
66
69
  See the [factory and migration guide](../../docs/agent-factories.md).
67
70
 
68
71
  ## RoboSprawl deployment recipe
69
72
 
70
- `roboshed.deployments.robosprawl.RoboSprawl` configures the concrete persistent
71
- orchestrator and Librarian recipe. Construct it with `memory_endpoint`,
72
- `additional_capabilities`, `subagents`, and `interaction_mode`. Call the object
73
- with an already-scoped sandbox, matching project slug, `endpoint_getter`, and
74
- optional `event_sinks` to receive a fresh unbuilt `Deployment`.
73
+ `roboshed.deployments.robosprawl.RoboSprawl` is the concrete lazy persistent
74
+ orchestrator and Librarian recipe. Construct `RoboSprawl()` without inputs;
75
+ supply the required scoped sandbox, endpoint getter, and memory endpoint with
76
+ `set_sandbox()`, `set_endpoint_getter()`, and `set_memory_endpoint()`.
77
+ `set_additional_capabilities()`, `set_specialists()`, `set_interaction_mode()`,
78
+ and `set_event_sinks()` supply optional inputs (empty sequences and
79
+ `interaction_mode=None` by default). A `None` mode inherits core's current output
80
+ setting, falling back to CLI when none is bound. Argument-free `build()` returns
81
+ a fresh root/background-agent tuple
82
+ or reports missing required inputs. `robosprawl` is an alias for this class.
75
83
 
76
84
  The recipe loads project memory and supplies project locations through initial
77
85
  messages. Its root follows the selected model getter; the Librarian uses its
78
- separate memory endpoint. Construction starts no agents and creates no
79
- directories. The application owns scope selection and runtime lifecycle.
86
+ separate memory endpoint. Configuration and building start no agents or provider
87
+ clients and create no project directories. Use a fresh recipe per new run;
88
+ setters snapshot the sandbox and sequence containers, while supplied endpoints
89
+ and capability/child objects remain caller-owned. The application owns scope
90
+ selection and runtime lifecycle. See the [migration example](../../docs/agent-factories.md#fixed-robosprawl-recipe).
80
91
 
81
92
  ## Conversation compaction
82
93
 
@@ -129,17 +140,16 @@ See the [migration guide](https://github.com/Tachion-Oy/roboz/blob/main/docs/con
129
140
  for low-level context fields and state ownership.
130
141
 
131
142
 
132
- ## Deployment instances
143
+ ## Deployable agent graphs
133
144
 
134
- Declare a `Deployment(agent=..., sandbox=...)` from `roboshed.deployments`.
135
- The root definition owns all recursive `subagents` and `background_agents`;
136
- both slots contain the same definition type. Configure the attached objects in
137
- place before building:
145
+ The root `DeployableAgent` owns recursive `subagents` and `background_agents`;
146
+ both slots contain the same definition type. Configure each object explicitly
147
+ before building:
138
148
 
139
149
  ```python
140
- deployment.sandbox.configure_scope(folder)
141
- deployment.event_sinks.append(dispatch)
142
- agent, background_agents = deployment.build()
150
+ sandbox.configure_scope(folder)
151
+ definition.set_attributes(permissions=sandbox.permissions())
152
+ agent, background_agents = definition.build(event_sinks=(dispatch,))
143
153
  ```
144
154
 
145
155
  Construct each application sandbox directly:
@@ -151,10 +161,9 @@ sandbox.configure_scope(folder)
151
161
 
152
162
  The host supplies `folder` at runtime. For now it is a direct child of the
153
163
  sandbox's existing `projects_dir`, with unchanged tiered permission behavior.
154
- Default persistence paths follow that scope, and CLI sinks are disabled unless
155
- requested. Startup memory is agent configuration, not deployment configuration.
156
- Each build captures its scope and sink registrations, so later reconfiguration
157
- cannot redirect an existing agent.
164
+ Default persistence paths follow that scope. Startup memory and endpoints are
165
+ agent configuration. Each build creates fresh runtime state; applications can
166
+ supply an agent-specific sink factory for persistence.
158
167
 
159
168
  The Librarian constructor declares its standard maintenance sequence:
160
169
  snapshots, consolidation, retention, then cadence. Pass its sandbox and the
@@ -163,9 +172,10 @@ a background agent. The orchestrator also takes the configured sandbox and
163
172
  captures its permission policy when constructed.
164
173
 
165
174
  Invoke the returned agent directly and retain the background agents for control.
166
- Do not reconfigure the same deployment concurrently. Repeated builds create fresh
167
- runtimes and built-in persistence sinks, but supplied endpoint/sink objects remain
168
- caller-owned. The old factories, host protocols, and result bundles are removed.
175
+ Repeated builds create fresh runtimes and bindings, but supplied endpoints,
176
+ capabilities, and sinks remain caller-owned. No execution state is retained on
177
+ the definition. The old deployment wrapper, factories, host protocols, and
178
+ result bundles are removed.
169
179
  Use core's `roboz.llm.ModelSelector` for lazy model selection.
170
180
  `roboz.dependencies` supplies exact dependency registration and binding;
171
181
  `roboshed.dependency_health` supplies isolated `inspect_dependencies`, probes,
@@ -179,4 +189,4 @@ The `robosprawl` skill from `roboshed.skills` covers sandbox orientation and the
179
189
  HUD file-link/markdown contract. The external RoboSprawl application may select
180
190
  it through `Capability(auto_loaded_skills=(robosprawl,))`. Concrete paths,
181
191
  endpoints, extra capabilities, and specialist definitions remain application
182
- choices. The `RoboSprawl` recipe assembles them into a fresh `Deployment`.
192
+ choices. The `robosprawl` recipe assembles and builds a fresh agent graph.
@@ -19,48 +19,59 @@ permissions = PermissionPolicy.local(Path("./sandbox"))
19
19
  agent = DeployableAgent(
20
20
  name="file_worker",
21
21
  system_prompt="Complete the user's task, then call stop.",
22
- agent_endpoint=MockLLMEndpoint([
23
- {"action": "stop", "rationale": "done", "value": "Ready."}
24
- ]),
25
- capabilities=(
22
+ default_capabilities=(
26
23
  Capability(tools=(stop,)),
27
- FileCommands(permissions),
28
- FileEditing(permissions),
24
+ FileCommands(),
25
+ FileEditing(),
29
26
  ),
30
- ).build()
27
+ )
28
+ agent.set_agent_endpoint(MockLLMEndpoint([
29
+ {"action": "stop", "rationale": "done", "value": "Ready."}
30
+ ]))
31
+ agent.set_attributes(permissions=permissions)
32
+ agent, background_agents = agent.build()
31
33
  result, messages = agent.invoke()
32
34
  ```
33
35
 
34
36
  `roboshed.capabilities` provides `FileCommands`, `FileEditing`, `Compactification`,
35
37
  `ConversationSnapshots`, `MemoryConsolidation`, `ArtifactRetention`, and
36
38
  `MaintenanceCadence`, alongside the `tools` and `skills` modules. Applications
37
- choose capabilities through each agent definition's `capabilities` tuple.
39
+ choose fixed capabilities through `default_capabilities` and append application
40
+ extensions with `add_capabilities()`.
38
41
  A capability owns its tools and skills. Generic `DeployableAgent` definitions
39
42
  live in `roboz.deployment`.
40
43
  Reusable `orchestrator` and `librarian` constructors live in `roboshed.agents`.
41
44
  The orchestrator owns stop and guarded file work, and the Librarian owns
42
45
  snapshots, consolidation, retention, and cadence. Root-only application
43
- capabilities go in `Deployment.additional_capabilities`, after the agent's
44
- built-in capability loop, without unpacking the role defaults.
46
+ capabilities append after the agent's protected defaults, without unpacking the
47
+ role definitions.
45
48
 
46
- Each capability uses an explicit endpoint override or its agent's default.
47
- Runtime controls remain separate. Direct standalone builds accept explicit
48
- `PermissionPolicy` and sandbox inputs.
49
+ Each capability declares the typed attributes it reads from its owning
50
+ `DeployableAgent`. Runtime controls remain separate. Use `set_attributes()` to
51
+ supply standalone permission policies and sandbox inputs before building.
49
52
 
50
53
  See the [factory and migration guide](../../docs/agent-factories.md).
51
54
 
52
55
  ## RoboSprawl deployment recipe
53
56
 
54
- `roboshed.deployments.robosprawl.RoboSprawl` configures the concrete persistent
55
- orchestrator and Librarian recipe. Construct it with `memory_endpoint`,
56
- `additional_capabilities`, `subagents`, and `interaction_mode`. Call the object
57
- with an already-scoped sandbox, matching project slug, `endpoint_getter`, and
58
- optional `event_sinks` to receive a fresh unbuilt `Deployment`.
57
+ `roboshed.deployments.robosprawl.RoboSprawl` is the concrete lazy persistent
58
+ orchestrator and Librarian recipe. Construct `RoboSprawl()` without inputs;
59
+ supply the required scoped sandbox, endpoint getter, and memory endpoint with
60
+ `set_sandbox()`, `set_endpoint_getter()`, and `set_memory_endpoint()`.
61
+ `set_additional_capabilities()`, `set_specialists()`, `set_interaction_mode()`,
62
+ and `set_event_sinks()` supply optional inputs (empty sequences and
63
+ `interaction_mode=None` by default). A `None` mode inherits core's current output
64
+ setting, falling back to CLI when none is bound. Argument-free `build()` returns
65
+ a fresh root/background-agent tuple
66
+ or reports missing required inputs. `robosprawl` is an alias for this class.
59
67
 
60
68
  The recipe loads project memory and supplies project locations through initial
61
69
  messages. Its root follows the selected model getter; the Librarian uses its
62
- separate memory endpoint. Construction starts no agents and creates no
63
- directories. The application owns scope selection and runtime lifecycle.
70
+ separate memory endpoint. Configuration and building start no agents or provider
71
+ clients and create no project directories. Use a fresh recipe per new run;
72
+ setters snapshot the sandbox and sequence containers, while supplied endpoints
73
+ and capability/child objects remain caller-owned. The application owns scope
74
+ selection and runtime lifecycle. See the [migration example](../../docs/agent-factories.md#fixed-robosprawl-recipe).
64
75
 
65
76
  ## Conversation compaction
66
77
 
@@ -113,17 +124,16 @@ See the [migration guide](https://github.com/Tachion-Oy/roboz/blob/main/docs/con
113
124
  for low-level context fields and state ownership.
114
125
 
115
126
 
116
- ## Deployment instances
127
+ ## Deployable agent graphs
117
128
 
118
- Declare a `Deployment(agent=..., sandbox=...)` from `roboshed.deployments`.
119
- The root definition owns all recursive `subagents` and `background_agents`;
120
- both slots contain the same definition type. Configure the attached objects in
121
- place before building:
129
+ The root `DeployableAgent` owns recursive `subagents` and `background_agents`;
130
+ both slots contain the same definition type. Configure each object explicitly
131
+ before building:
122
132
 
123
133
  ```python
124
- deployment.sandbox.configure_scope(folder)
125
- deployment.event_sinks.append(dispatch)
126
- agent, background_agents = deployment.build()
134
+ sandbox.configure_scope(folder)
135
+ definition.set_attributes(permissions=sandbox.permissions())
136
+ agent, background_agents = definition.build(event_sinks=(dispatch,))
127
137
  ```
128
138
 
129
139
  Construct each application sandbox directly:
@@ -135,10 +145,9 @@ sandbox.configure_scope(folder)
135
145
 
136
146
  The host supplies `folder` at runtime. For now it is a direct child of the
137
147
  sandbox's existing `projects_dir`, with unchanged tiered permission behavior.
138
- Default persistence paths follow that scope, and CLI sinks are disabled unless
139
- requested. Startup memory is agent configuration, not deployment configuration.
140
- Each build captures its scope and sink registrations, so later reconfiguration
141
- cannot redirect an existing agent.
148
+ Default persistence paths follow that scope. Startup memory and endpoints are
149
+ agent configuration. Each build creates fresh runtime state; applications can
150
+ supply an agent-specific sink factory for persistence.
142
151
 
143
152
  The Librarian constructor declares its standard maintenance sequence:
144
153
  snapshots, consolidation, retention, then cadence. Pass its sandbox and the
@@ -147,9 +156,10 @@ a background agent. The orchestrator also takes the configured sandbox and
147
156
  captures its permission policy when constructed.
148
157
 
149
158
  Invoke the returned agent directly and retain the background agents for control.
150
- Do not reconfigure the same deployment concurrently. Repeated builds create fresh
151
- runtimes and built-in persistence sinks, but supplied endpoint/sink objects remain
152
- caller-owned. The old factories, host protocols, and result bundles are removed.
159
+ Repeated builds create fresh runtimes and bindings, but supplied endpoints,
160
+ capabilities, and sinks remain caller-owned. No execution state is retained on
161
+ the definition. The old deployment wrapper, factories, host protocols, and
162
+ result bundles are removed.
153
163
  Use core's `roboz.llm.ModelSelector` for lazy model selection.
154
164
  `roboz.dependencies` supplies exact dependency registration and binding;
155
165
  `roboshed.dependency_health` supplies isolated `inspect_dependencies`, probes,
@@ -163,4 +173,4 @@ The `robosprawl` skill from `roboshed.skills` covers sandbox orientation and the
163
173
  HUD file-link/markdown contract. The external RoboSprawl application may select
164
174
  it through `Capability(auto_loaded_skills=(robosprawl,))`. Concrete paths,
165
175
  endpoints, extra capabilities, and specialist definitions remain application
166
- choices. The `RoboSprawl` recipe assembles them into a fresh `Deployment`.
176
+ choices. The `robosprawl` recipe assembles and builds a fresh agent graph.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "roboshed"
3
- version = "0.1.1.dev1"
3
+ version = "0.1.1.dev2"
4
4
  description = "roboshed: optional building blocks for Roboz"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -9,7 +9,7 @@ license = "Apache-2.0"
9
9
  license-files = ["LICENSE"]
10
10
  import-names = ["roboshed"]
11
11
  classifiers = ["Development Status :: 2 - Pre-Alpha", "Typing :: Typed"]
12
- dependencies = ["roboz>=0.1.2.dev3,<0.2.0","pydantic>=2.12.4"]
12
+ dependencies = ["roboz>=0.1.2.dev4,<0.2.0","pydantic>=2.12.4"]
13
13
 
14
14
  [build-system]
15
15
  requires = ["hatchling>=1.32"]
@@ -21,25 +21,30 @@ LIBRARIAN_AGENT_DESCRIPTION: Final[str] = (
21
21
 
22
22
  def librarian(
23
23
  sandbox: Sandbox,
24
- agent_names: Collection[str],
24
+ watched_agent_names: Collection[str],
25
25
  *,
26
26
  agent_endpoint: EndpointLike | None,
27
27
  ) -> DeployableAgent:
28
28
  """Configure maintenance for the sandbox and foreground agent names."""
29
- return DeployableAgent(
29
+ agent = DeployableAgent(
30
30
  name=LIBRARIAN_AGENT_NAME,
31
31
  description=LIBRARIAN_AGENT_DESCRIPTION,
32
- interaction_mode=None,
33
32
  is_agentic=False,
34
33
  automatic_tool_prompt=False,
35
- agent_endpoint=agent_endpoint,
36
- capabilities=(
37
- ConversationSnapshots(sandbox=sandbox, agent_names=agent_names),
38
- MemoryConsolidation(sandbox=sandbox, agent_names=agent_names),
39
- ArtifactRetention(sandbox=sandbox),
40
- MaintenanceCadence(sandbox=sandbox, agent_names=agent_names),
34
+ default_capabilities=(
35
+ ConversationSnapshots(),
36
+ MemoryConsolidation(),
37
+ ArtifactRetention(),
38
+ MaintenanceCadence(),
41
39
  ),
42
40
  )
41
+ agent.set_agent_endpoint(agent_endpoint)
42
+ agent.set_interaction_mode(None)
43
+ agent.set_attributes(
44
+ sandbox=sandbox,
45
+ watched_agent_names=frozenset(watched_agent_names),
46
+ )
47
+ return agent
43
48
 
44
49
 
45
50
  __all__ = ["LIBRARIAN_AGENT_DESCRIPTION", "librarian"]
@@ -30,21 +30,23 @@ def orchestrator(
30
30
  initial_messages: Sequence[Path | str] = (),
31
31
  ) -> DeployableAgent:
32
32
  """Configure the orchestrator for an already-configured sandbox."""
33
- return DeployableAgent(
33
+ agent = DeployableAgent(
34
34
  name="orchestrator",
35
35
  description="Coordinates ongoing user goals and specialist agents.",
36
36
  system_prompt=ORCHESTRATOR_PROMPT,
37
- agent_endpoint=agent_endpoint,
38
- capabilities=(
37
+ default_capabilities=(
39
38
  Capability(tools=(stop,)),
40
- FileCommands(sandbox.permissions()),
41
- FileEditing(sandbox.permissions()),
39
+ FileCommands(),
40
+ FileEditing(),
42
41
  ),
43
42
  subagents=tuple(subagents),
44
43
  background_agents=tuple(background_agents),
45
- interaction_mode=interaction_mode,
46
- initial_messages=tuple(initial_messages),
47
44
  )
45
+ agent.set_agent_endpoint(agent_endpoint)
46
+ agent.set_interaction_mode(interaction_mode)
47
+ agent.set_initial_messages(initial_messages)
48
+ agent.set_attributes(permissions=sandbox.permissions())
49
+ return agent
48
50
 
49
51
 
50
52
  __all__ = ["ORCHESTRATOR_PROMPT", "orchestrator"]