feat: initialize agents from a2a template
All checks were successful
build / build (push) Successful in 2s
All checks were successful
build / build (push) Successful in 2s
This commit is contained in:
@@ -84,6 +84,11 @@ when you deploy through the control plane).
|
||||
|
||||
Your tools:
|
||||
|
||||
- init_agent_template(name, description)
|
||||
— initialize agents/<name>/ from the
|
||||
installed a2a-pack `a2a init` template.
|
||||
Use this FIRST for a new project, then
|
||||
edit the generated files.
|
||||
- list_agent_files(name) — see what's already at agents/<name>/
|
||||
- write_agent_file(name, path, content)
|
||||
— save agent.py / a2a.yaml / requirements.txt
|
||||
@@ -116,8 +121,10 @@ Discipline:
|
||||
|
||||
- Pick a kebab-case slug for ``name`` (e.g. ``research-agent``,
|
||||
``csv-sanitizer``). Class name is PascalCase from the slug.
|
||||
- Write ALL THREE files (agent.py, a2a.yaml, requirements.txt) before
|
||||
testing — partial scaffolds break ``a2a card``.
|
||||
- For a new project, call init_agent_template first. Then read/edit the
|
||||
generated files instead of inventing boilerplate from memory.
|
||||
- Ensure all three core files (agent.py, a2a.yaml, requirements.txt)
|
||||
exist before testing — partial scaffolds break ``a2a card``.
|
||||
- Always run test_agent_in_sandbox before deploying. If exit_code != 0,
|
||||
read stderr, edit the offending file, retest. Do NOT deploy a broken
|
||||
scaffold.
|
||||
|
||||
@@ -14,6 +14,7 @@ import re
|
||||
import tarfile
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from importlib import resources
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import boto3
|
||||
@@ -111,6 +112,36 @@ def build_tools(ctx: ToolContext) -> list[Any]:
|
||||
s3 = _s3(ctx)
|
||||
_ensure_bucket(s3, bucket)
|
||||
|
||||
@tool
|
||||
def init_agent_template(
|
||||
name: str,
|
||||
description: str = "A new A2A agent",
|
||||
) -> str:
|
||||
"""Initialize ``agents/<name>/`` from the installed a2a-pack template.
|
||||
|
||||
Use this FIRST for a new project. It writes the same baseline files
|
||||
as ``a2a init`` for the SDK version installed in this runtime:
|
||||
``agent.py``, ``a2a.yaml``, and ``requirements.txt``. After this,
|
||||
edit those files with ``read_agent_file`` + ``write_agent_file`` to
|
||||
implement the user's requested behavior.
|
||||
"""
|
||||
try:
|
||||
files = _render_a2a_init_template(name, description=description)
|
||||
prefix = _agent_prefix(name)
|
||||
except (OSError, ValueError) as exc:
|
||||
return json.dumps({"error": str(exc)})
|
||||
written: list[dict[str, Any]] = []
|
||||
for path, content in files.items():
|
||||
key = prefix + path
|
||||
s3.put_object(
|
||||
Bucket=bucket,
|
||||
Key=key,
|
||||
Body=content.encode("utf-8"),
|
||||
ContentType="text/plain; charset=utf-8",
|
||||
)
|
||||
written.append({"path": key, "size": len(content)})
|
||||
return json.dumps({"ok": True, "agent": name, "files": written})
|
||||
|
||||
@tool
|
||||
def list_agent_files(name: str) -> str:
|
||||
"""List every file under ``agents/<name>/`` in the user's workspace.
|
||||
@@ -434,7 +465,7 @@ def build_tools(ctx: ToolContext) -> list[Any]:
|
||||
})
|
||||
|
||||
return [
|
||||
list_agent_files, write_agent_file, read_agent_file,
|
||||
init_agent_template, list_agent_files, write_agent_file, read_agent_file,
|
||||
test_agent_in_sandbox, cp_deploy_tarball, cp_refresh_agent,
|
||||
list_a2a_pack, read_a2a_pack,
|
||||
]
|
||||
@@ -479,3 +510,37 @@ def _read_entrypoint(bundle: bytes) -> str | None:
|
||||
|
||||
def _class_name(slug: str) -> str:
|
||||
return "".join(p.capitalize() for p in re.split(r"[-_]+", slug) if p) or "MyAgent"
|
||||
|
||||
|
||||
def _render_a2a_init_template(
|
||||
name: str,
|
||||
*,
|
||||
description: str = "A new A2A agent",
|
||||
) -> dict[str, str]:
|
||||
_validate_name(name)
|
||||
class_name = _class_name(name)
|
||||
return {
|
||||
"agent.py": _render_sdk_template(
|
||||
"agent.py.tmpl",
|
||||
name=name,
|
||||
class_name=class_name,
|
||||
description=description,
|
||||
),
|
||||
"a2a.yaml": _render_sdk_template(
|
||||
"a2a.yaml.tmpl",
|
||||
name=name,
|
||||
class_name=class_name,
|
||||
),
|
||||
"requirements.txt": _render_sdk_template("requirements.txt.tmpl"),
|
||||
}
|
||||
|
||||
|
||||
def _render_sdk_template(template: str, /, **vars: str) -> str:
|
||||
text = (
|
||||
resources.files("a2a_pack.cli.templates")
|
||||
.joinpath(template)
|
||||
.read_text(encoding="utf-8")
|
||||
)
|
||||
for key, value in vars.items():
|
||||
text = text.replace("{{ " + key + " }}", value)
|
||||
return text
|
||||
|
||||
Reference in New Issue
Block a user