Fix: adopt AgentFile.loadAgent() and drop the unused loadApp() - #832
Open
AmaadMartin wants to merge 4 commits into
Open
Fix: adopt AgentFile.loadAgent() and drop the unused loadApp()#832AmaadMartin wants to merge 4 commits into
AmaadMartin wants to merge 4 commits into
Conversation
added 4 commits
August 8, 2026 17:27
loadApp() synthesizes an App named after the agent, which would override the loader key Runner uses as appName, and validateAppName rejects agent names that validateAgentName accepts. No caller can adopt it without a behaviour change, so remove it. adk-python keeps App synthesis off the loader for the same reason.
The graph route and the adk run watcher both open-coded the narrowing loadAgent() already performs. The A2A bootstrap also rebuilt the loaded value as `adkApp ?? agent`, which is the loaded value itself.
Three tests now build the same duck-typed AgentFile, so build it in one place.
The bootstrap kept the hand-written narrowing this change removes everywhere else. load() is memoized, so the second call is free. Restore the App-identity assertion the loadApp() test rewrite dropped, and pin that the bootstrap calls loadAgent().
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.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
N/A
Problem:
AgentFileindev/src/utils/agent_loader.tsexposesloadAgent()andloadApp(), and neither has a production caller. Four production sites spellloadAgent()out by hand asisApp(loaded) ? loaded.rootAgent : loaded.loadApp()cannot be adopted at all: for a bare agent file it synthesizesApp({name: agent.name}), andRunnerreadsinput.app?.name ?? input.appName(core/src/runner/runner.ts:155), so that name would replace the loader key used for session and artifact scoping.validateAppName(/^[a-zA-Z][a-zA-Z0-9_-]*$/) is also stricter thanvalidateAgentName(/^[\p{ID_Start}$_][\p{ID_Continue}$_-]*$/u), so an agent named_internalloads throughload()and then makesloadApp()throw.Solution: I deleted
loadApp()and adoptedloadAgent()at the three sites that only need the root agent: the event-graph route, theadk runreload watcher, and the A2A bootstrap. That bootstrap also passedadkApp ?? agenttogetRunner, which is always the loaded value, so it passesload()directly now.adk-pythonsplits the same union the same way: the loader hasload_agent()and noload_app(), narrowing lives on the consumer as_get_root_agent(cli/api_server.py:832), and App synthesis takes the caller's app key (_to_app(agent_or_app, app_name),cli/cli.py:60). One site keeps theisAppternary, becausecli_run.tsneeds the root agent and theApp | undefinedtogether.Collision check: I listed all 300 open PRs on the fork and read the diffs of the 13 that touch
agent_loader.ts,adk_api_server.tsorcli_run.ts. None adds or removesloadApp/AgentFile.loadAgent. #731 removes the separateAgentLoader.listApps()/getAppFile()pair and rewrites the same integration test line, so I edited that test in place rather than deleting the block.Type-checker note: this branch adds three
as unknown aslines, all in test fakes. Each replaces an identical cast that the same file already had:git show main:<file> | grep -c 'as unknown as'and the same count on this branch are equal for both test files. A structural fake cannot satisfyAgentFileorAgentLoaderbecause both declare private fields. Noany, no@ts-expect-error, noeslint-disable, no coverage suppression.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change.
[x] All unit tests pass locally.
npx vitest run --project unit:dev dev/test/server/adk_api_server_test.ts dev/test/cli/cli_run_test.ts dev/test/utils/agent_loader_test.ts— 94 passed.Every new test was run against the unfixed code and fails there:
loadAgent()returns the raw unionloads the rootAgent of an App file via loadAgent()expected true to be falseload()rebuilds the App under a different nameloads the rootAgent of an App file via loadAgent()expected 'renamed' to be 'test_app_default'load()+ ternaryshould return graph for an App-exporting agent fileexpected "spy" to be called at least onceload()+ ternaryshould build the Runner from the App of an App-exporting agent fileexpected "spy" to be called at least oncegetRunnerreceives the root agent, not the unionshould build the Runner from the App of an App-exporting agent fileexpected +0 to be 1load()+ ternaryshould rebuild the runner from the reloaded agent fileexpected "spy" to be called at least onceshould keep the current runner when the reloaded file fails to loadexpected "warn" to be called with argumentsThree existing tests were retargeted in place rather than added alongside, because each one called
loadApp(), which this PR deletes. They are'loads an app via loadApp() and rootAgent via loadAgent()'and'synthesizes an App when loadApp() is called on a BaseAgent file'indev/test/utils/agent_loader_test.ts, and'should synthesize App when loadApp() is called on BaseAgent file'intests/integration/app_loader/app_loader_test.ts. The first keeps itstest_app_defaultApp-identity assertion, which the second mutation above pins. No other test was changed, and none was deleted.Gates on the pushed commit:
npm run build,npm run lintandnpm run ts:checkall pass.ts:checkreports 287 pre-existing errors in unrelated test files, and none in any file this branch touches.CI is green on all three runners for the head commit. An earlier commit needed two re-runs, both for infrastructure flakes unrelated to this branch: the dev build hit
ECONNRESETwhile it downloaded the ADK Web zip from GitHub, andcore/test/code_executors/unsafe_local_code_executor_test.tstimed out at 5000 ms on the Windows runner.tests/integration/app_loader/app_loader_test.tscould not run here. ItsbeforeAllrunsnpm installper fixture, and this machine's registry returns403 Forbidden - GET https://us-npm.pkg.dev/.../@a2a-js%2fsdk. The failure is in the hook, before any assertion, and it reproduces onmain.Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any necessary setup or configuration.
I ran a local end-to-end check with no mocks: real
AgentLoader, real esbuild compile, real HTTP. To repeat it:npm ci && npm run build.plain/agent.ts(exportsrootAgent) andwrapped/app.ts(exportsapp).new AdkApiServer({agentsDir, sessionService, a2a: true})with a session that already holds a function-call event.GET /apps/<name>/users/u1/sessions/<id>/events/<eventId>/graphreturns 200, anddotSrcnamesplain_agentandwrapped_agent.GET /a2a/<name>/.well-known/agent-card.jsonreturns 200 for both.new AgentFile(path).loadAppisundefined, andloadAgent()returns the root agent for both file shapes.Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.