temporal-engine subchart (off by default), with the RBAC the engine needs - #198
Merged
Conversation
…needs The engine's standalone chart becomes a subchart of the umbrella chart, off by default. Enabling it is deliberately TWO steps: 1. temporal-engine.enabled=true -- deploy worker + gateway 2. agent-orchestrator.config.agentEngine=temporal -- route turns to it Step 1 alone changes no behaviour, which is what makes the rollout reversible: the engine can be deployed, watched and rolled back before a single turn depends on it. Takes a Temporal ADDRESS rather than bundling a server — the platform already runs a cluster (confirmed with the maintainer), so enabling this adds no stateful component. That was the strongest argument against the whole change. ## RBAC: what the catch-up work actually needs The imported chart only granted `toolruns` create/get, which was true when it was written and is not now: - `secrets` create/get/update/patch. This grant is what keeps a credential out of Temporal's event history: the pre-flight writes resolved values into a Secret and returns only its NAME, so nothing a workflow can see holds credential material and the kubelet is the only reader. - `agentruns` create/get, granted ONLY when the NATS bridge is enabled — bridged pod agents launch the ordinary AgentRun an unmodified upstream agent expects. - `integrationroutes` get/list/watch, on a NEW gateway ServiceAccount: the gateway watches routes for deterministic dispatch and previously ran without an identity at all. Each mirrors a grant agent-orchestrator already holds, so enabling the engine does not widen the release's blast radius — it gives an equivalent one to a second workload. ## Values reused rather than duplicated Defaults point at the orchestrator's own OPENAI_API_KEY secret and the shared callback secret, so one key serves both engines. `catalog.namespace` defaults to the release namespace instead of a hardcoded one. `qdrant.collectionPrefix` defaults to `te-` and says why: both engines index tools/skills/agents with DIFFERENT payload schemas, so a shared collection would have each reading records it cannot decode. ## Verified, and now verifiable Nothing in CI rendered charts/agent-controller at all, so a broken subchart template would have shipped silently. A new job lints and renders this one in both shapes that matter: defaults (no catalog-sync without Qdrant, no AgentRun grant without the bridge) and everything-on, because an optional block that only breaks when enabled is the one nobody notices. Rendered standalone, since the umbrella chart pulls open-webui and nats from remote repos. Locally: helm lint clean, both renders parse as YAML. ## Fork residue dropped docs/platform (a Bitovi-specific ArgoCD/ECR deployment kit) and the Makefile's `ecr-push` target are gone, and the Makefile now just runs the same four checks CI does. The README's standalone-install section is replaced by the two-step subchart flow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Uj1SJ41DJJ8woZM7fd3DQ
Working notes for landing ADR 0036 as five reviewable PRs rather than one 33-commit branch, with what each one is actually asking a reviewer to check. Two things it records rather than leaves implicit. The ADR moved to PR 1 and out of the dependency chain, so the design can be rejected before anyone reads 17k lines of Go — if the answer is "we don't want a second agent loop", that is the only PR that needed to exist. And PR 5 (flip the default) is deliberately unwritten, because its precondition is an e2e run that has not happened; writing it now would assert a result nobody has. Also lists three findings that stand on their own merits whether or not the engine is ever enabled, including a gap on the existing LangGraph path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Uj1SJ41DJJ8woZM7fd3DQ
imaustink
reviewed
Aug 7, 2026
imaustink
left a comment
Owner
There was a problem hiding this comment.
🚢 I triggered the jobs again
This was referenced Aug 7, 2026
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.
Fourth PR in the sequence from #194 (ADR 0036), following #196 and #197. Adds the
temporal-enginesubchart.enabled: false, so this changes no behaviour. It's the last PR in the sequence that doesn't.Enabling the engine is deliberately two steps:
Step 1 alone changes nothing, which is what makes the rollout reversible — the engine can be deployed, watched and rolled back before a single turn depends on it.
Takes a Temporal address rather than bundling a server, so enabling it adds no stateful component. (That was the strongest argument against this whole thing; it doesn't apply, since the platform already runs Temporal.)
The part worth actual scrutiny: RBAC
The chart arrived from the fork granting only
toolrunscreate/get, which was true when it was written and isn't now.templates/rbac.yamladds:secretscreate/get/update/patch. This grant is the mechanism that keeps credentials out of Temporal's event history: the authorization pre-flight writes resolved values into a Secret and returns only the object's name, so nothing a workflow can see holds credential material and the kubelet is the only reader. Without this grant the engine cannot resolve a per-user credential at all.agentrunscreate/get, granted only when the NATS bridge is enabled — bridged pod agents launch the ordinaryAgentRunan unmodified upstream agent expects.integrationroutesget/list/watch, on a new gateway ServiceAccount. The gateway watches routes for deterministic dispatch and previously ran with no identity at all.Each mirrors a grant
agent-orchestratoralready holds, so enabling the engine doesn't widen the release's blast radius — it gives an equivalent one to a second workload. Worth checking that claim rather than taking it.Values reused rather than duplicated
Defaults point at the orchestrator's own
OPENAI_API_KEYsecret and the shared callback secret, so one key serves both engines.catalog.namespacedefaults to the release namespace instead of a hardcoded one.qdrant.collectionPrefixdefaults tote-, and the reason is in the values file: both engines index tools/skills/agents with different payload schemas, so a shared collection would have each reading records it cannot decode. Prefixing keeps them side by side in one instance.This adds the first CI job that renders
charts/agent-controllerat allNothing in CI templated this chart before, so a broken subchart template would ship silently — that's true of the other three subcharts today and remains so; this PR only covers the new one.
Rendered standalone rather than through the umbrella chart, because the parent pulls
open-webuiandnatsfrom remote repos and templating it needs ahelm dependency buildplus a network round trip to validate a subchart that has neither.Both shapes are checked, and the second one is the point: defaults must render the minimum (no catalog-sync without Qdrant, no
agentrunsgrant without the bridge), and everything-on must render at all — an optional block that only breaks when enabled is the one nobody notices.Fork residue dropped
docs/platform/(a Bitovi-specific ArgoCD + ECR deployment kit) and the Makefile'secr-pushtarget. The Makefile now just runs the same four checks CI does.What this PR does not do
It doesn't enable anything. The next step — flipping
agentEnginetotemporal— needs thee2e/suite run underAGENT_ENGINE=temporal, and that hasn't happened. 581 unit tests passing is precisely the evidence ADR 0030 says isn't enough: "none of the defects above were visible to unit tests; every one required the assembled system to be running."Locally:
helm lintclean, both renders parse, engine module green (12 packages), orchestrator 581 tests + typecheck clean.🤖 Generated with Claude Code
https://claude.ai/code/session_018Uj1SJ41DJJ8woZM7fd3DQ