feat: agent definition v2 (registry, persistence, developerInstructions channel)
Registry: POST /tasks accepts agent_name, loading <name>.json from repo-root agents/ (traversal-guarded, skill-pack re-validated); agent and agent_name together is a 400. Persistence: tasks gains agent_name/agent_version/agent_instructions (migrate + PG schema), returned by GET /tasks; stored prompt stays clean. Channel: local and docker dispatch pass --developer-instructions to host.py dispatch -> create_thread(developerInstructions=...); run/fork do not re-send. Cloud executor has no such channel, so the worker falls back to the v1 marked header in the in-memory dispatch prompt only (DB prompt stays clean). Goal/coordinator tasks still reject instructions. Tests: test_agent_def_v2.py (7 tests) + updated v1 suite.
This commit is contained in:
1 parent
7bb3c37a10
commit
1672ab9ff2
8 files changed
+361
-35
No files matched your search
+33
-5
@@ -39,11 +39,33 @@ today, with every boundary written down instead of implied:
|
||||
is rejected, so a typo or a v2 idea cannot masquerade as v1 behaviour.
|
||||
* Unknown top-level or defaults keys are rejected for the same
|
||||
reason: a declarative file must fail on typos, not silently ignore
|
||||
them. Definition identity (name/version/skills) is echoed in the
|
||||
creation response and, via the prompt header, in the stored prompt;
|
||||
v1 adds NO new tasks-table column, so ``GET /tasks`` shows the
|
||||
resolved fields and the header, not a separate ``agent`` column.
|
||||
That column is v2, not something v1 pretends to have.
|
||||
them.
|
||||
|
||||
v2 (this file, plus server/worker/sandbox/host changes) closes the
|
||||
three v1 boundaries that were explicitly left open:
|
||||
|
||||
* Registry: definitions can live as files under repo-root ``agents/``
|
||||
(``default_agents_dir()``) and be referenced by name
|
||||
(``agent_name``) instead of only inline. The server never loads a
|
||||
definition from a caller-supplied path; it only loads
|
||||
``<name>.json`` under the registry dir, with the traversal guard
|
||||
in ``load_agent_definition``.
|
||||
* Persistence: ``tasks`` gains ``agent_name`` / ``agent_version`` /
|
||||
``agent_instructions`` columns (see ``migrate_tasks_table``), so
|
||||
``GET /tasks`` shows the definition identity and instructions, and
|
||||
the worker no longer has to reconstruct them from a prompt header.
|
||||
* Real channel: for local/docker executors, instructions travel as
|
||||
``--developer-instructions`` on the host.py top-level command,
|
||||
through ``sandbox`` into ``host.py dispatch`` ->
|
||||
``create_thread(developerInstructions=...)``. The stored prompt
|
||||
stays clean. For the generic cloud executor, which has no such
|
||||
channel, the worker falls back to the v1 marked header in the
|
||||
in-memory dispatch prompt only (DB prompt stays clean) -- that
|
||||
fallback is the documented cloud boundary, not a claim that the
|
||||
cloud runner honours developerInstructions. Goal and coordinator
|
||||
tasks still reject instructions in v2: the goal loop and the
|
||||
coordinator parent do not pass instructions through, and silently
|
||||
dropping them there would be worse than rejecting them.
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -62,6 +84,12 @@ _TOP_LEVEL_KEYS = ("name", "version", "description", "instructions",
|
||||
"skills", "defaults")
|
||||
_DEFAULTS_KEYS = ("model", "effort", "approval", "executor", "plan")
|
||||
SKILLS_DIR = Path(__file__).resolve().parent / "skills"
|
||||
AGENTS_DIR = Path(__file__).resolve().parent.parent / "agents"
|
||||
|
||||
|
||||
def default_agents_dir():
|
||||
"""Repo-root ``agents/`` directory (definitions live with code)."""
|
||||
return AGENTS_DIR
|
||||
|
||||
|
||||
def list_known_skills(skills_dir=None):
|
||||
|
||||
Reference in new issue
Block a user