Retarget Agents surface from opencode to Hermes (enterpriseaiframework-8a9) - #39
Draft
baron-3dl wants to merge 10 commits into
Draft
Retarget Agents surface from opencode to Hermes (enterpriseaiframework-8a9)#39baron-3dl wants to merge 10 commits into
baron-3dl wants to merge 10 commits into
Conversation
…truth (enterpriseaiframework-8a9) The Agents epic (-da7) built the resident surface on 'opencode serve' + an opencode-web-console proxy, making a 'hermes agent' literally an opencode process. That conflated the Agents surface with the Code/coding surface (Baron's ruling 2026-08-10: 'opencode is for the coding app; don't conflate the coding UX with the agent UX'). This lands the corrected source of truth so the design no longer encodes the conflation, and pins the exact Hermes runtime for the build: - new docs/design/records/agents-surface-hermes-retarget.md: the buildable spec — image nousresearch/hermes-agent:v2026.8.3, 'hermes gateway run' daemon, HERMES_HOME /opt/data PVC, config.yaml seeded with our gateway provider (http://gateway:4000/v1), empty securityContext (s6 needs root), console = exec-attach 'hermes --tui', per-file change list, live proof plan. - agents-surface.md: retarget banner; chassis contracts (1/3/4/5/6) still stand. - design.md §12: resident process is 'hermes gateway run', console exec-attaches 'hermes --tui', HERMES_HOME=/opt/data; runtime chart jyje/hermes-agent. Code/workspace (Contract 6 frozen set) untouched. Build tracked in -8a9. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (enterpriseaiframework-8a9) Proved the Hermes runtime end to end on the real cluster and captured the exact working recipe before touching the repo template: - agent-baron-rudi retargeted opencode->Hermes and is Running: image nousresearch/hermes-agent:v2026.8.3, 'hermes gateway run' under s6, HERMES_HOME /opt/data on its PVC, inference routed through our gateway (http://gateway:4000/v1) on the integrated <baron::agents/rudi> key. Live 'hermes chat -q' answered correctly. - deploy/agent/hermes-config.yaml.tmpl: the seeded config.yaml (gateway provider, model deepseek-v4-flash@deepinfra, context_length 128000, max_tokens 8000) with the two integration traps documented (bare model id, and missing context_length / over-cap max_tokens both misreport as 'context length exceeded'). - retarget record: 'Validated live' section. Key finding flagged for Baron — the Hermes image REQUIRES root at boot (s6 chowns then drops to uid 10000); the opencode template's runAsNonRoot/drop-ALL hardening kills it. Agent process still runs non-root (10000); only s6 init is root. Console today: kubectl exec -it deploy/agent-baron-rudi -c agent -- hermes --tui. In-portal terminal (agent_console.py exec bridge) deferred — needs a control-plane redeploy, held while the camp is live. Code surface untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t (enterpriseaiframework-8a9) Portal create() now provisions a Hermes pod, not opencode: - 64-agent.template.yaml: Hermes image, 'hermes gateway run', HERMES_HOME=/opt/data PVC, per-agent config.yaml ConfigMap + root init-seed, empty securityContext (s6 needs root then drops to 10000), no inbound port. Connector envFrom + BYO/checksum placeholders kept. - agents.py: DEFAULT_MODEL=deepseek-v4-flash@deepinfra (+ context_length/max_tokens defaults), HERMES_IMAGE (agent no longer reuses the workspace image), render() seeds config.yaml, create() drops the opencode server password + the obsolete agent-entrypoint ConfigMap, console_target() resolves the owned running pod for pods/exec 'hermes --tui'. Console bridge (agent_console.py -> pods/exec), RBAC, provision-agent.sh parity, and the control-plane redeploy still to come. Code/workspace surface untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…aiframework-8a9) The Agents 'Open console' is now a real browser terminal into the running Hermes pod, replacing the opencode-SPA proxy: - agent_console.py rewritten: serves an xterm terminal page at /agents/<name>/ and a WebSocket that bridges the browser to the Kubernetes pods/exec subresource running 'hermes --tui' in the caller's OWN pod (owner-scoped by agents.console_target, same guard as stop/start/delete). Reuses the SA token + cluster CA; v4.channel.k8s.io framing. - xterm.js vendored into portal_static (self-hosted, CSP stays strict, no CDN). - 39-control-plane-rbac.yaml: grant pods/exec create (create-only, fixed command 'hermes --tui'). Documented posture change from the opencode design's 'NO pods/exec' — forced by the terminal-in console Baron asked for; scoped by the owner guard, not RBAC. Multi-tenant + multiple agents per user were already the chassis (create/stop/start/delete, owner-scoped); this makes them run Hermes and console into Hermes. Deploy (control-plane rebuild + agent-assets ConfigMap + RBAC apply) is the next step. py_compile clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…the tool ConfigMap (enterpriseaiframework-8a9) Hermes reads messaging connectors from the environment, so the deployment-wide agent-entrypoint tool ConfigMap (opencode's shell tools, finding 49's force-apply clobber) is retired. The test now asserts a created agent has no such ConfigMap and injects the three connector Secrets via envFrom (optional). Full control-plane suite green: 179 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sh render Hermes, drop opencode connector scripts (enterpriseaiframework-8a9)
- provision-agent.sh: Hermes image default, __CONTEXT_LENGTH__/__MAX_TOKENS__ sed,
config-inputs CFGSUM matching agents.py, -key Secret holds only OPENAI_API_KEY
(OPENCODE_SERVER_PASSWORD retired), no agent-entrypoint ConfigMap. Connector Secret
KEYS kept as AGENT_* (control-plane parity); Hermes env mapping documented as TODO.
- hermes-up.sh: validate chat via connector env presence + inference via config.yaml
base_url/model, not opencode tools/OPENCODE_MODEL.
- 63-agent-common.yaml: drop the port-4096 ingress rule (console is pods/exec now).
- deploy.sh: agent-assets ships only 64-agent.template.yaml.
- delete deploy/agent/{entrypoint.sh,agent-email,agent-slack,agent-discord,agentws.py,
EMAIL.md,SLACK.md,DISCORD.md}.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…8a9)
- harness: in-pod exec branches probe connector env presence + config.yaml inference.
- test_agent_model_api_config: base_url/model read from the config ConfigMap, template
kinds ConfigMap not Service.
- test_hermes_up: chat validated by connector env presence, inference via config.yaml;
two in-pod checks, not three.
- test_agent_{chat,email}_provisioning: -key Secret holds only OPENAI_API_KEY; drop the
retired agent-entrypoint tool-ConfigMap tests.
- delete test_agent_{slack,discord,email}.py, chat_fakes.py, test_agent_{chat,email}_
entrypoint.py, test_agent_assets.py (all test deleted opencode connector tooling).
- new test_agent_no_chat_server.py preserves the no-chat/mail-server + no-inbound-route
invariants against the Hermes template.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| the socket) means a non-owner or a stopped agent gets the real 404/409 as a page, rather | ||
| than a blank terminal that fails silently on connect.""" | ||
| await agents.console_target(user, name) | ||
| return HTMLResponse(_terminal_page(name)) |
…encode AGENT_* (enterpriseaiframework-ff6) The connector wizard shipped BROKEN: it wrote Slack/Discord/email tokens under opencode's AGENT_* keys, but 'hermes gateway run' reads native names (SLACK_BOT_TOKEN, DISCORD_BOT_TOKEN, EMAIL_ADDRESS, ...), so a browser-wired connector connected to nothing (found live on rudi's Discord). Retargets all three synced copies to the native names, in lockstep: - agents.py CONNECTORS, portal_static/app.js CONNECTOR_FIELDS, provision-agent.sh allowlists. - Adds *_ALLOWED_USERS (Slack/Discord) + EMAIL_ALLOW_ALL_USERS: Hermes denies unknown senders by default, so without them a connector connects but answers no one (the rudi symptom). Wizard hints say so; blank = secure default. - Email loses username/port/security fields — Hermes auto-detects ports and TLS. - test_portal_connectors retargeted; the parity + browser-form + wiring tests keep the three copies honest. Control-plane suite: 179 passed. Fixes the ff6 gap that made every new agent's connectors broken until hand-patched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nterpriseaiframework-8a9) The retarget added agent-<user>-<name>-config (the seeded Hermes config.yaml), but the delete path never removed it, so deleting an agent left an orphaned ConfigMap behind — and re-creating the same name would adopt a stale config. Delete now removes it; the delete test asserts configmaps are gone alongside deployments/services/secrets/PVCs. Found by running delete on a live portal-created agent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nv-var names (enterpriseaiframework-ff6) Follows the control-plane connector rename (3664edd): AGENT_* -> Hermes-native (SLACK_BOT_TOKEN, DISCORD_BOT_TOKEN, EMAIL_ADDRESS, ...), *_DEFAULT_CHANNEL -> *_HOME_CHANNEL, sum keys <LABEL>_CONFIG_SUM. - hermes-up.sh: chat env-presence probe checks the native SLACK_/DISCORD_ names. - agent_provision_harness.py: connector-sum state file uses <LABEL>_CONFIG_SUM. - test_agent_chat_provisioning.py / test_hermes_up.py: config-files + assertions native. - test_agent_email_provisioning.py: email fixture drops the opencode-only fields Hermes auto-detects (username, SMTP/IMAP port, security); new test_a_dropped_opencode_email_field_is_now_refused asserts the shell rejects them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Retargets the resident Agents surface from
opencode serveto Hermes Agent (NousResearch), fixing the conflation of the Agents UX with the coding UX. Deployed live and verified; branch is what the running control-plane (c7b81c0) was built from.What changed
hermes gateway run(imagenousresearch/hermes-agent:v2026.8.3,HERMES_HOME=/opt/dataPVC,config.yamlseeded to our gateway ondeepseek-v4-flash@deepinfra), empty securityContext (s6 boots root → drops to uid 10000), config-seed init container. No inbound port.Open consoleis now an in-browser xterm terminal that execshermes --tuivia the Kubernetespods/execsubresource (owner-scoped), replacing the opencode web-console proxy. xterm vendored; RBAC gainspods/execcreate.agents.py+ operatorprovision-agent.sh) retargeted with matching CFGSUM; opencode connector shell scripts +entrypoint.shdeleted; NetworkPolicy drops the 4096 ingress.docs/design/records/agents-surface-hermes-retarget.md+design.md §12.Tests
tests/) agent suite green after retarget.Verified live
Portal-created agent
scoutreached Running and answered inference through the gateway; console page serves owner-200 / non-owner-404; control-plane SA can exec. Camp workspaces untouched by the deploy.Follow-up
enterpriseaiframework-ff6— connector env-var name translation (Slack/Discord/email don't auto-enable untilAGENT_*keys map to Hermes's native names). Additive; core create/console/multi-tenant unaffected.🤖 Generated with Claude Code