From 45386a1f14754987945a29d07831daa117a9f13e Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 18 May 2026 19:12:47 -0300 Subject: [PATCH] harden agent builder render guidance --- agent_builder/builder.py | 33 +++++++++++++++++++++++++++++++++ tests/test_builder_prompt.py | 19 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/test_builder_prompt.py diff --git a/agent_builder/builder.py b/agent_builder/builder.py index 2d17e15..56e8dad 100644 --- a/agent_builder/builder.py +++ b/agent_builder/builder.py @@ -61,6 +61,35 @@ runtime: Names must be plain Debian package slugs (lowercase, ``[a-z0-9.+-]``). Don't reach for this for Python deps — those go in ``requirements.txt``. +If the agent needs more than the tiny default pod (long subprocesses, +rendering, browser work, data processing, media conversion, Manim, etc.), +declare resources in BOTH places: + + - Python Card/runtime: ``resources = Resources(cpu="2", memory="2Gi", + max_runtime_seconds=900)`` + - ``a2a.yaml`` for the Gitea/Argo scaffold, which cannot import user code + before the image is built: + +```yaml +runtime: + resources: + cpu: "2" + memory: 2Gi + max_runtime_seconds: 900 +``` + +For render/media agents, subprocesses must 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. + +For Manim presentation agents specifically, generate a stable PDF fallback +that does not require Manim rendering. If HTML/video rendering is requested, +generate ``class GeneratedDeck(Slide)`` and call +``manim-slides render --CE -ql GeneratedDeck``; do not assume raw +``manim`` is enough for a Manim Slides deck. + And a ``requirements.txt`` listing any extra deps beyond a2a-pack itself (pandas, httpx, etc. — the base image ships a2a-pack already when you deploy through the control plane). @@ -113,6 +142,10 @@ Discipline: scaffold. - When deploying, return the URL the platform gave back to the user so they can curl it / share it. + - After cp_deploy_tarball returns, compare ``live_skills[].input_schema`` + with the skill signatures you wrote. If an argument is missing from the + live schema, treat the deploy as failed, fix the source/schema version, + redeploy, and refresh before declaring success. - Don't fabricate functionality the user didn't ask for. One or two well-scoped @skill methods beats a kitchen sink. """ diff --git a/tests/test_builder_prompt.py b/tests/test_builder_prompt.py new file mode 100644 index 0000000..2711471 --- /dev/null +++ b/tests/test_builder_prompt.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +import unittest + +from agent_builder.builder import SYSTEM_PROMPT + + +class BuilderPromptTests(unittest.TestCase): + def test_prompt_requires_resource_mirror_for_heavy_agents(self) -> None: + self.assertIn("declare resources in BOTH places", SYSTEM_PROMPT) + self.assertIn("resources = Resources", SYSTEM_PROMPT) + self.assertIn("runtime:", SYSTEM_PROMPT) + self.assertIn("max_runtime_seconds", SYSTEM_PROMPT) + + def test_prompt_requires_live_schema_check_and_manim_contract(self) -> None: + self.assertIn("live_skills[].input_schema", SYSTEM_PROMPT) + self.assertIn("class GeneratedDeck(Slide)", SYSTEM_PROMPT) + self.assertIn("manim-slides render --CE -ql", SYSTEM_PROMPT) + self.assertIn("render: bool = False", SYSTEM_PROMPT)