Skip to content

feat(devtools): add Reasoning Engine server compatibility routes and headers parser (Agent Engine Deployment Artifact registry fix part 1)#440

Open
AmaadMartin wants to merge 3 commits into
mainfrom
feat/reasoning-engine-server-support
Open

feat(devtools): add Reasoning Engine server compatibility routes and headers parser (Agent Engine Deployment Artifact registry fix part 1)#440
AmaadMartin wants to merge 3 commits into
mainfrom
feat/reasoning-engine-server-support

Conversation

@AmaadMartin

@AmaadMartin AmaadMartin commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Please ensure you have read the contribution guide https://google.github.io/adk-docs/contributing-guide/ before creating a pull request.

Link to Issue or Description of Change

  1. Link to an existing issue (if applicable):

• Closes: #none
• Related: #none

  1. Or, if no issue exists, describe the change:

Problem:
Vertex AI's Reasoning Engine execution gateway and liveness checks impose two key constraints:

  1. Containers must pass liveness probes at / and /health without redirects (Vertex AI kills containers that return 3xx codes, which broke ADK because it redirected / to /dev-ui).
  2. Vertex AI forwards query payloads with duplicate content-type headers (Content-Type: application/json,application/json), which causes Express's standard body-parser to skip parsing and results in empty request bodies {}.

Solution:
Implemented native routing in adk_api_server.ts for /health and / endpoints to return 200 OK when the Debug UI is disabled. Added a custom raw-body fallback stream listener on the POST /api/reasoning_engine query endpoint to parse incoming payloads manually if standard body-parser was skipped.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Summary of passed test results:

✓ |unit:dev| dev/test/server/adk_api_server_test.ts (45 tests) 3797ms
✓ AdkWebServer > Reasoning Engine > should return 200 OK on health endpoints when debug UI is disabled 99ms
✓ AdkWebServer > Reasoning Engine > should query the agent using reasoning_engine route with valid JSON 42ms
✓ AdkWebServer > Reasoning Engine > should auto-create session if not exists on reasoning_engine query 56ms
✓ AdkWebServer > Reasoning Engine > should support raw body query and parse headers workaround 83ms
✓ AdkWebServer > Reasoning Engine > should return 400 if appName is missing 36ms
✓ AdkWebServer > Reasoning Engine > should return 500 if execution fails 34ms

Files tested:

• dev/test/server/adk_api_server_test.ts

Manual End-to-End (E2E) Tests:

Manually deployed and verified querying the weather tool agent on Vertex AI Reasoning Engines with unmocked traffic.

Checklist

  • I have read the CONTRIBUTING.md https://github.com/google/adk-js/blob/main/CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.

Additional context

None.

@AmaadMartin AmaadMartin changed the title feat(devtools): add Reasoning Engine server compatibility routes and headers parser feat(devtools): add Reasoning Engine server compatibility routes and headers parser (Agent Engine Deployment Artifact registry fix part 1) Jun 16, 2026
Comment thread dev/src/server/adk_api_server.ts Outdated
Comment on lines +784 to +804
let session = await this.sessionService.getSession({
appName,
userId,
sessionId,
});
if (!session) {
this.logger.info(
`Session ${sessionId} not found. Creating it automatically.`,
);
session = await this.sessionService.createSession({
appName,
userId,
sessionId,
state: {},
});
}
await using agentFile = await this.agentLoader.getAgentFile(appName);
const agent = await agentFile.load();
const runner = await this.getRunner(agent, appName);
const events: Event[] = [];
const abortController = new AbortController();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have getOrCreateSession

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Refactored to use the existing getOrCreateSession helper.

Comment thread dev/src/server/adk_api_server.ts Outdated
Comment on lines +800 to +821
await using agentFile = await this.agentLoader.getAgentFile(appName);
const agent = await agentFile.load();
const runner = await this.getRunner(agent, appName);
const events: Event[] = [];
const abortController = new AbortController();
req.on('close', () => {
abortController.abort();
});
for await (const e of runner.runAsync({
userId,
sessionId,
newMessage,
stateDelta,
abortSignal: abortController.signal,
})) {
events.push(e);
}
res.json({output: events});
} catch (e: unknown) {
const error = `Failed to run agent via Reasoning Engine API: ${e}`;
res.status(500).json({error});
this.logger.error(error);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very similar to run_sse can we move the common logic to the same place?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored the core execution block (agent load, runner fetch, run loop, and event streaming) into a shared executeAgentRun helper. This helper is now reused in /run, /run_sse, and the Reasoning Engine query endpoints to keep them clean and consistent.

return this.runnerCache[appName];
}

private async executeAgentRun(options: {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it as generator and then no need to introduce a onEvent callback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants