Decision
Adopt opencode (the maintained anomalyco/opencode TS build, MIT, npm-distributed, OpenAI-partnered) as taOS's agent harness, installed from upstream with no fork. It serves two roles through one design:
- The taOS assistant (replacing the current framework-less direct-LLM chat).
- The App Builder code-generation engine.
The user-facing model is one host assistant, one brain — not two competing assistants. The only thing that physically separates is where untrusted code executes.
Why opencode
- Headless HTTP server (OpenAPI 3.1 + SSE + typed JS/TS SDK) is a cleaner driver surface than OpenClaw's ACP or Hermes' api_server. The host-side adapter is one codec mapping opencode SSE events to taOS's fixed 6-kind reply vocabulary (delta/final/tool_call/tool_result/reasoning/error).
tinyagentos/adapters/acp_adapter.py is the copy template.
- Point it at the LiteLLM proxy (the deployer already injects
OPENAI_BASE_URL + a per-agent virtual key) and it inherits the synced model-management that just shipped (permitted set == key scope), so its 75+ providers collapse to taOS's one governed surface.
- Multi-agent / persona / session natively, plus custom tools in any language and a per-tool wildcard permission system. That is exactly the configurability the two roles need.
- Fork-free: add as a store framework like OpenClaw/Hermes. No reinventing an agent loop.
Current state being replaced
tinyagentos/routes/taos_agent.py (/api/taos-agent/chat) is a direct streaming LiteLLM chat: system prompt from docs/taos-agent-manual.md, user-picked model, no tools, no MCP, no agent loop. It can talk about taOS but cannot act. opencode gives the assistant real tool-calling + actions.
Architecture: one host assistant + a sandboxed build lane
Host assistant (privileged)
- Runs on the host, not in a container, so it can diagnose and fix taOS (logs, systemctl, config, the LiteLLM proxy, containers). A sandboxed assistant cannot recover a broken install.
- Two frontends over one instance: the taOS web panel (via opencode's headless HTTP/SSE API) and the native TUI as
taosagent in the terminal.
- Tool surface is a curated taOS-management set exposed via
routes/mcp.py (read logs, snapshot+repair config, restart service, manage agents/proxy/containers), NOT raw arbitrary shell.
- Runs as its own service, independent of
tinyagentos.service, so it can restart the main server when that is what is broken.
Sandboxed build-execution lane
- The host assistant handles "build me an app" via a dedicated app-creation persona, but the actual untrusted codegen executes in a disposable container sandbox it supervises.
- Rationale: opencode isolation is application-level only (permission matching, no OS/syscall sandbox), and the host instance is root. Agent-generated, prompt-injectable, often-shared code must never execute with host-root privilege. The container is the hard boundary; opencode permissions are a second layer.
- Tier: local-only scratch builds may use an in-process restricted persona; anything bound for the community store goes in the sandbox, no exception.
- Decision rule: one assistant, one brain, but untrusted code never executes in the privileged host process.
taosagent recovery CLI
"Run taosagent in the terminal and ask it to fix your install." This is the sanctioned exception to the no-terminal-for-end-users rule: one memorable command, then natural language, not a sequence of apt/systemctl spells. Three hard constraints:
- Runs when taOS is down. Zero dependency on
tinyagentos.service or the web stack; bootstraps its own context (finds the install, reads config/logs/journal). Shipped by the bootstrap installer so it is always present.
- Survives the LLM chicken-and-egg. If the LiteLLM proxy is the broken thing, the agent still needs to reason: run deterministic, no-LLM diagnostics first (port checks, service status, config lint, disk/journal scan), and provide a fallback/direct model path that bypasses the proxy.
- Repairs are vetted recipes, not freestyle root shell. A defined toolset (restart service, rebuild SPA, repair/snapshot config, restart proxy, unwedge a container, free a stuck port) that the LLM selects and explains while the recipe performs the action: snapshot-first, confirm destructive, audit-log every repair.
Guardrail stack (before agent-built apps reach the public store)
- Constrain the build persona into a
.taosapp factory: locked Plan/Build permissions, a scaffold template it edits rather than invents, and a taos_app_validate / taos_app_package custom tool giving a hard pass/fail loop before the user sees anything.
- Re-validate every artifact through the existing untrusted pipeline with zero trust on "the agent built it":
userspace/package.py manifest validation, zip-slip defense, userspace/url_guard.py SSRF guard, capability-broker grant gating.
- Automated pre-gate feeding the human approval step: manifest lint, permission-diff, dependency/secret scan, static analysis of web bundles.
- Web apps only at launch. The
container app type ships an arbitrary OCI image with no provenance, scan, or egress controls; gate it behind registry allowlist + digest pinning + image scan + default-deny egress before it is publicly shareable.
Security boundaries
- Host assistant is the highest-privilege component in taOS. Curated tool surface, snapshot-first + confirm on destructive actions, audit log.
OPENCODE_SERVER_PASSWORD is not a security boundary: bind 127.0.0.1 only, per-session-generated, never on taos.local/mDNS.
- The recovery TUI must be auth-gated: "GUI is down" must not mean "unauthenticated host agent with fix powers."
- Pin
anomalyco/opencode at a version/digest; explicitly avoid the abandoned Go opencode-ai/opencode.
Real (not free) work
- The SSE to 6-kind adapter codec.
- An
opencode branch in tinyagentos/framework_model_sync.py plus adding it to the reconciler allowlist (currently hard-coded to ('openclaw','hermes')).
- Reconcile opencode's multi-session model against taOS's per-agent turn serialization (pin one session per agent).
- Measure host + cluster footprint to set manifest tiers.
Phased path
- Spike the adapter: install pinned opencode in one container, point it at LiteLLM, deploy a test agent, run one turn, confirm a non-permitted model call is rejected by LiteLLM. Copy the acp_adapter mapping table.
- Host assistant MVP: opencode on the host with the taOS-management MCP tools +
taosagent TUI, replacing routes/taos_agent.py. Deterministic diagnostics + fallback model path.
- App Builder: app-creation persona + the
.taosapp factory tools + sandboxed build lane + the opaque-origin iframe live preview. Ships before share.
- Model-sync codec for opencode.
- Share-to-store + the automated pre-gate. Web apps only initially.
Blocked / dependencies
- Share-to-store depends on gitaos + taOS accounts.
- The npm version-probe gap (no GitHub-release version tracking for npm-distributed frameworks) is shared with OpenClaw and tracked under the framework version-selection work.
Decision
Adopt opencode (the maintained
anomalyco/opencodeTS build, MIT, npm-distributed, OpenAI-partnered) as taOS's agent harness, installed from upstream with no fork. It serves two roles through one design:The user-facing model is one host assistant, one brain — not two competing assistants. The only thing that physically separates is where untrusted code executes.
Why opencode
tinyagentos/adapters/acp_adapter.pyis the copy template.OPENAI_BASE_URL+ a per-agent virtual key) and it inherits the synced model-management that just shipped (permitted set == key scope), so its 75+ providers collapse to taOS's one governed surface.Current state being replaced
tinyagentos/routes/taos_agent.py(/api/taos-agent/chat) is a direct streaming LiteLLM chat: system prompt fromdocs/taos-agent-manual.md, user-picked model, no tools, no MCP, no agent loop. It can talk about taOS but cannot act. opencode gives the assistant real tool-calling + actions.Architecture: one host assistant + a sandboxed build lane
Host assistant (privileged)
taosagentin the terminal.routes/mcp.py(read logs, snapshot+repair config, restart service, manage agents/proxy/containers), NOT raw arbitrary shell.tinyagentos.service, so it can restart the main server when that is what is broken.Sandboxed build-execution lane
taosagent recovery CLI
"Run
taosagentin the terminal and ask it to fix your install." This is the sanctioned exception to the no-terminal-for-end-users rule: one memorable command, then natural language, not a sequence ofapt/systemctlspells. Three hard constraints:tinyagentos.serviceor the web stack; bootstraps its own context (finds the install, reads config/logs/journal). Shipped by the bootstrap installer so it is always present.Guardrail stack (before agent-built apps reach the public store)
.taosappfactory: locked Plan/Build permissions, a scaffold template it edits rather than invents, and ataos_app_validate/taos_app_packagecustom tool giving a hard pass/fail loop before the user sees anything.userspace/package.pymanifest validation, zip-slip defense,userspace/url_guard.pySSRF guard, capability-broker grant gating.containerapp type ships an arbitrary OCI image with no provenance, scan, or egress controls; gate it behind registry allowlist + digest pinning + image scan + default-deny egress before it is publicly shareable.Security boundaries
OPENCODE_SERVER_PASSWORDis not a security boundary: bind 127.0.0.1 only, per-session-generated, never ontaos.local/mDNS.anomalyco/opencodeat a version/digest; explicitly avoid the abandoned Goopencode-ai/opencode.Real (not free) work
opencodebranch intinyagentos/framework_model_sync.pyplus adding it to the reconciler allowlist (currently hard-coded to('openclaw','hermes')).Phased path
taosagentTUI, replacingroutes/taos_agent.py. Deterministic diagnostics + fallback model path..taosappfactory tools + sandboxed build lane + the opaque-origin iframe live preview. Ships before share.Blocked / dependencies