Summary
POST /api/agents with a local: template that does not exist returns 200 Created and provisions a running container with no template content at all — no CLAUDE.md, no template.yaml, no skills. The caller gets a normal-looking agent object and no indication that the template they asked for was never found.
A nonexistent github: template is rejected correctly, so the two source types behave inconsistently.
Verified on v0.8.5 (b8cf94ca).
Repro
curl -X POST -H "Authorization: Bearer $T" -H 'Content-Type: application/json' \
-d '{"name":"p1-nope","template":"local:does-not-exist"}' \
http://localhost:8000/api/agents
Actual — 200:
{"name":"p1-nope","type":"business-assistant","status":"stopped","port":2228,
"container_id":"33995259fd81…","template":"local:does-not-exist",
"runtime":"claude-code","base_image_version":"0.8.5"}
The type field is a fabricated default; nothing in the response says the template was missing.
Resulting agent — an empty shell that reports itself running:
$ curl .../api/agents/p1-nope/info
{"has_template":false,"agent_name":"p1-nope","template_name":"local:does-not-exist",
"message":"No template.yaml found - this agent was created without a template","status":"running"}
$ docker exec agent-p1-nope ls /home/developer
.bashrc .cache .claude .claude-agent .config .local .mcp.json .profile
.ssh .tmp .trinity content mcp-servers # no CLAUDE.md, no template.yaml
Contrast — the github: path gets it right
-d '{"name":"p1-badrepo","template":"github:abilityai/definitely-not-a-real-repo"}'
→ 400 {"detail":"Repository 'abilityai/definitely-not-a-real-repo' was not found or is private.
If it is private, add your GitHub token in Settings or ask an admin to configure the platform token."}
That is the correct shape: fail fast, explain, create nothing.
Impact
The agent starts, shows running in the fleet list, and answers chat — as a generic assistant with zero instructions, skills, or MCP config. The user discovers this only by talking to it and noticing it has no idea what it is supposed to do, having already spent a container and a data volume.
The most likely way to hit this is not the UI dropdown but the MCP create_agent tool, which takes a free-text template id — exactly the surface used by the "Claude Code writes the agent, Trinity runs it" workflow, and exactly where a stale or hallucinated template id shows up. A renamed or newly-hidden template produces the same silent downgrade for anyone with a saved script.
Suggested direction
Resolve local: templates before provisioning and 400/404 on a miss, mirroring the github: path. If templateless creation is a deliberate capability, it should require an explicit opt-in (e.g. an empty/omitted template) rather than being the silent fallback for an unresolvable one.
Summary
POST /api/agentswith alocal:template that does not exist returns 200 Created and provisions a running container with no template content at all — noCLAUDE.md, notemplate.yaml, no skills. The caller gets a normal-looking agent object and no indication that the template they asked for was never found.A nonexistent
github:template is rejected correctly, so the two source types behave inconsistently.Verified on v0.8.5 (
b8cf94ca).Repro
Actual — 200:
{"name":"p1-nope","type":"business-assistant","status":"stopped","port":2228, "container_id":"33995259fd81…","template":"local:does-not-exist", "runtime":"claude-code","base_image_version":"0.8.5"}The
typefield is a fabricated default; nothing in the response says the template was missing.Resulting agent — an empty shell that reports itself running:
Contrast — the
github:path gets it rightThat is the correct shape: fail fast, explain, create nothing.
Impact
The agent starts, shows
runningin the fleet list, and answers chat — as a generic assistant with zero instructions, skills, or MCP config. The user discovers this only by talking to it and noticing it has no idea what it is supposed to do, having already spent a container and a data volume.The most likely way to hit this is not the UI dropdown but the MCP
create_agenttool, which takes a free-text template id — exactly the surface used by the "Claude Code writes the agent, Trinity runs it" workflow, and exactly where a stale or hallucinated template id shows up. A renamed or newly-hiddentemplate produces the same silent downgrade for anyone with a saved script.Suggested direction
Resolve
local:templates before provisioning and 400/404 on a miss, mirroring thegithub:path. If templateless creation is a deliberate capability, it should require an explicit opt-in (e.g. an empty/omittedtemplate) rather than being the silent fallback for an unresolvable one.