diff --git a/agent_builder/builder.py b/agent_builder/builder.py index 137dfb0..fc29ada 100644 --- a/agent_builder/builder.py +++ b/agent_builder/builder.py @@ -94,17 +94,18 @@ runtime: ``` For render/media/data agents, commands that create user-visible files MUST run -through ``await ctx.workspace_shell(...)`` or ``await ctx.workspace_python(...)`` -and write under ``/workspace/outputs/...``. Do not use in-process -``asyncio.create_subprocess_exec`` for durable outputs; the agent container is -not workspace-mounted, so files created in ``/tmp`` or the image filesystem can -vanish after the request. Commands must still be bounded with timeouts and broad -exception handling, and failures must return structured JSON instead of -crashing the worker. Use ``render: bool = False`` by default and expose every -public skill argument with concrete type hints so the live ``input_schema`` -contains the full call surface. If a render command returns nonzero after -emitting a usable file, preserve the file under ``/workspace/outputs/...`` and -include the command failure as a warning instead of dropping the result. +through ``await ctx.workspace_shell(...)`` or ``await ctx.workspace_python(...)``. +The platform sandbox persists ``/workspace`` writes directly and captures changed +files elsewhere in the guest rootfs under ``outputs/rootfs-captures/...``. Do +not use in-process ``asyncio.create_subprocess_exec`` for durable outputs; the +agent container is not workspace-mounted or rootfs-captured, so files created in +``/tmp`` or the image filesystem can vanish after the request. Commands must +still be bounded with timeouts and broad exception handling, and failures must +return structured JSON instead of crashing the worker. Use ``render: bool = False`` +by default and expose every public skill argument with concrete type hints so +the live ``input_schema`` contains the full call surface. If a render command +returns nonzero after emitting a usable file, preserve the file and include the +command failure as a warning instead of dropping the result. For Manim presentation agents specifically, generate a stable PDF fallback that does not require Manim rendering. If HTML/video rendering is requested, diff --git a/agent_builder/skills/a2apack-agent-authoring/SKILL.md b/agent_builder/skills/a2apack-agent-authoring/SKILL.md index 4d5b56f..54866db 100644 --- a/agent_builder/skills/a2apack-agent-authoring/SKILL.md +++ b/agent_builder/skills/a2apack-agent-authoring/SKILL.md @@ -130,9 +130,10 @@ If a skill calls `ctx.workspace_backend()` or `ctx.workspace`, declare If a skill runs code, renderers, converters, or data tools that create downloadable files, run them through `await ctx.workspace_shell(...)` or -`await ctx.workspace_python(...)` and make the command write under -`/workspace/outputs/...`. In-process subprocesses write inside the agent pod, -not the caller's mounted workspace. +`await ctx.workspace_python(...)`. The sandbox persists `/workspace` writes +directly and mirrors changed files elsewhere in the guest rootfs under +`outputs/rootfs-captures/...`. In-process subprocesses write inside the agent +pod, not the caller's mounted or rootfs-captured workspace. When invoking an inner DeepAgents graph, pass `config={"recursion_limit": 500}` to `graph.ainvoke(...)` or diff --git a/agent_builder/skills/agent-quality-review/SKILL.md b/agent_builder/skills/agent-quality-review/SKILL.md index 779da3f..baf9b80 100644 --- a/agent_builder/skills/agent-quality-review/SKILL.md +++ b/agent_builder/skills/agent-quality-review/SKILL.md @@ -38,8 +38,9 @@ Check these items: - Deterministic tools do exact work; no fake canned-response tools. - File-producing skills call `ctx.write_artifact` and `ctx.emit_artifact`. - Commands that create downloadable outputs run through `ctx.workspace_shell` - or `ctx.workspace_python` and write under `/workspace/outputs/...`. Plain - subprocesses in the agent container are not durable workspace writes. + or `ctx.workspace_python`; `/workspace` writes persist directly and other + changed sandbox rootfs files are mirrored under `outputs/rootfs-captures/...`. + Plain subprocesses in the agent container are not durable workspace writes. - External calls, secrets, workspace access, pricing, and resources are declared on the class. diff --git a/agent_builder/skills/deepagents-implementation-patterns/SKILL.md b/agent_builder/skills/deepagents-implementation-patterns/SKILL.md index e964291..141a6a1 100644 --- a/agent_builder/skills/deepagents-implementation-patterns/SKILL.md +++ b/agent_builder/skills/deepagents-implementation-patterns/SKILL.md @@ -25,7 +25,8 @@ RUNTIME_SKILLS_ROOT = "/outputs/research-agent/.deepagents/skills/" SYSTEM_PROMPT = """\ You are a careful research agent. Use project skills for workflow rules and -write durable files under /workspace/outputs/. +use workspace-backed tools for durable files. Prefer /workspace/outputs/ for +stable output paths. """ diff --git a/agent_builder/skills/workspace-artifact-safety/SKILL.md b/agent_builder/skills/workspace-artifact-safety/SKILL.md index 41b0633..8245c1b 100644 --- a/agent_builder/skills/workspace-artifact-safety/SKILL.md +++ b/agent_builder/skills/workspace-artifact-safety/SKILL.md @@ -29,9 +29,9 @@ backend = ctx.workspace_backend() graph = create_deep_agent(model=model, backend=backend, skills=skill_sources or None) ``` -Write durable model-created files under `/workspace/outputs/...` in prompts. -When writing through `ctx.workspace`, use workspace-relative paths such as -`outputs/report.md`. +For stable, human-readable paths, ask model-created files to use +`/workspace/outputs/...`. When writing through `ctx.workspace`, use +workspace-relative paths such as `outputs/report.md`. ## Artifact Pattern @@ -77,10 +77,12 @@ async def run_checked(script: str, timeout_s: int = 120) -> dict[str, str | int] } ``` -Commands should write user-visible files under `/workspace/outputs/...`; that -path is backed by the caller's workspace bucket. Do not use -`asyncio.create_subprocess_exec(...)` for durable outputs. Plain subprocesses -run inside the agent container, which is not mounted to the caller workspace. +Commands may write to `/workspace/outputs/...` for stable paths, or to normal +tool defaults such as `/tmp`, `/root`, or `/app`. The platform sandbox mirrors +changed files outside `/workspace` into `outputs/rootfs-captures/...`. Do not +use `asyncio.create_subprocess_exec(...)` for durable outputs. Plain subprocesses +run inside the agent container, which is not mounted to the caller workspace and +is not rootfs-captured. If a nonzero command still produced a usable output, preserve the output and include the command failure as a warning instead of discarding the file. diff --git a/requirements.txt b/requirements.txt index 5a0c646..cbc204f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -a2a-pack>=0.1.8 +a2a-pack>=0.1.9 httpx>=0.27 boto3>=1.34 deepagents>=0.5.0 diff --git a/tests/test_builder_prompt.py b/tests/test_builder_prompt.py index d03a47f..d245e8d 100644 --- a/tests/test_builder_prompt.py +++ b/tests/test_builder_prompt.py @@ -38,8 +38,8 @@ class BuilderPromptTests(unittest.TestCase): def test_prompt_requires_workspace_mounted_execution_for_outputs(self) -> None: self.assertIn("ctx.workspace_shell", SYSTEM_PROMPT) self.assertIn("ctx.workspace_python", SYSTEM_PROMPT) - self.assertIn("/workspace/outputs/...", SYSTEM_PROMPT) - self.assertIn("not workspace-mounted", SYSTEM_PROMPT) + self.assertIn("outputs/rootfs-captures/...", SYSTEM_PROMPT) + self.assertIn("not workspace-mounted or rootfs-captured", SYSTEM_PROMPT) def test_prompt_and_backend_load_packaged_builder_skills(self) -> None: expected = { @@ -66,7 +66,7 @@ class BuilderPromptTests(unittest.TestCase): self.assertIn('config={"recursion_limit": 500}', files["deepagents-implementation-patterns/SKILL.md"]) self.assertIn("ctx.write_artifact", files["workspace-artifact-safety/SKILL.md"]) self.assertIn("ctx.workspace_shell", files["workspace-artifact-safety/SKILL.md"]) - self.assertIn("/workspace/outputs/...", files["workspace-artifact-safety/SKILL.md"]) + self.assertIn("outputs/rootfs-captures/...", files["workspace-artifact-safety/SKILL.md"]) self.assertIn("live_skills[].input_schema", files["agent-quality-review/SKILL.md"]) self.assertIn("ctx.workspace_python", files["agent-quality-review/SKILL.md"])