fix(a2a): resolve a role's environment to a provisioned id (FA-14) - #146
Merged
Conversation
_provision() previously left environment_id null for every A2A-provisioned session: ensure_agent() never returns one, and no tenant sets provider.environmentId. Add EnvironmentResolver (a2a/environments.py), mirroring providers/provision.py's basename->name->id lookup exactly, and wire it into A2AAdapter.__init__ (cached for the adapter's lifetime, never re-read per call). Precedence: tenant.provider.environment_id overrides everything; else a role naming an environment resolves through EnvironmentResolver, which raises rather than silently returning null when the name can't be resolved; a role naming no environment legitimately resolves to None. Adds agent-templates/environments/ (cloud-orchestrator.json) and binds it to the served agent-orchestrator role so the fix has a real environment to resolve against in this repo, not just in tests. Jira: FA-14 (epic FA-2) Co-Authored-By: Claude Opus 4.8 <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.
Summary
A2AAdapter._provisionalways producedenvironment_id: nullfor A2A-provisioned sessions:ensure_agent()(anthropic provider) never returns one, and no tenant setsprovider.environmentId. This fixes the A2A provisioning path to resolverole["environment"]to a real provider environment id.agent-templates/a2a/environments.py(EnvironmentResolver), which mirrorsproviders/provision.py's existing basename -> name -> id lookup exactly (_env_basename_to_name+env_ids.get(...)), instead of inventing a new scheme. It readsenvironments/<basename>.jsonfor thename, and${FUZE_STATE_DIR:-/state}/environment-ids.json(the{name: id}map batch provisioning writes) for the id — both cached for the resolver's lifetime, never re-read per call.A2AAdapter.__init__as an injectableenvironment_resolvercallable (default: a realEnvironmentResolver()), so_provisionnever reads global state itself — it only calls the resolver._resolve_environment_id:tenant.provider.environment_id(valuesprovider.environmentId) — explicit per-tenant override, wins outright.environment, resolve it viaEnvironmentResolver. RaisesEnvironmentResolutionError(never silently falls back tonull) if the basename has no matchingenvironments/*.json, that file has noname, or the name has no provisioned id yet.None, not an error; falls back to whateverensure_agent()'s response carried, if anything.agent-templates/environments/cloud-orchestrator.json(this repo didn't have anenvironments/dir yet) and bound it to the servedagent-orchestratorrole (environment: cloud-orchestrator), so this fix has a real environment to resolve against in this repo's own dispatch path, not only in tests.Design note for reviewers
A role's
environmentis documented (role-manifest.schema.json) as a basename of a file in the same repo'sagent-templates/environments/. Since each onboarded repo runs its ownproviders/provision.pyagainst its own environments, and the A2A server'sFUZE_STATE_DIR/environment-ids.jsonis a single shared mount (a2a-sharedchart'sdeploy.stateConfigMap: a2a-state) across however many tenants it serves, I resolved basenames against this repo's ownagent-templates/environments/(sibling toa2a/, exactly mirroringprovision.py'sENV_DIRconstruction) rather than each tenant's checked-out repo. This keeps the fix a literal mirror of the existing provisioning pattern per the ticket's guardrail ("do not invent a new scheme") and doesn't touchloader.py's tenant-repo resolution. If the intent is instead per-tenant environment definitions, that's a bigger design question (how a single shared id-state file disambiguates environment names across repos) worth a follow-up ticket rather than folding into FA-14.Type of change
Checklist
feat/…lint,test,build,sast,secret-scan,dependency-scan) — pending CI runTest plan
cd agent-templates/a2a && python3 -m pytest -q --ignore=tests/test_server.py-> 126 passed, 2 failed (the 2 failures are pre-existing schema drift intest_role_manifest_schema.py, unrelated to this change — confirmed identical failure count/names onmainbefore this branch's changes).agent-templates/a2a/tests/test_environments.py(11 tests, all passing):EnvironmentResolverbasename->id resolution, caching (deletes backing files after first call, resolver still returns the cached id), unknown-basename error, name-with-no-provisioned-id error, missing-state-dir-still-errors-for-a-named-env; adapter-level precedence (tenant override wins, resolved role environment, no-environment role ->None, unresolvable named environment raises); and an end-to-endsend_messagetest assertingcreate_sessionreceives the resolved id, neverNone.tests/test_server.pyfails to collect (httpx2missing) both before and after this change — known/excluded per the ticket, not addressed here.Related issues
Jira FA-14 (epic FA-2)
Generated by Claude Code