Skip to content

feat(project): add project-aware invoke - #2115

Open
aidandaly24 wants to merge 15 commits into
aws:refactorfrom
aidandaly24:feat/project-aware-invoke
Open

feat(project): add project-aware invoke#2115
aidandaly24 wants to merge 15 commits into
aws:refactorfrom
aidandaly24:feat/project-aware-invoke

Conversation

@aidandaly24

@aidandaly24aidandaly24 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

Add project-aware invocation for Runtimes and Harnesses declared by the project enclosing the current directory.

  • add agentcore project invoke as an interactive picker for deployed project Runtimes and Harnesses on the default target
  • add explicit headless child commands:
    • agentcore project invoke runtime --name <name> --payload <payload>
    • agentcore project invoke harness --name <name> --prompt <prompt>
  • allow --name to be omitted when the project declares exactly one resource of that type
  • resolve logical project names to deployed physical IDs and regions through the selected deployment target and live CloudFormation stack
  • preserve the existing Runtime payload, content-type, response, output-file, and JSON behavior
  • preserve the existing Harness prompt, session, transcript, and chat behavior
  • reuse the Runtime and Harness invoke operations and TUI consoles instead of adding a third transport or presentation path
  • document project invoke in the CLI and generated Runtime templates

This PR intentionally does not define a project-specific Runtime payload or response contract. Runtime responses retain the existing raw invoke behavior, including raw SSE. Gateway project invoke remains outside this scope.

The project deployment prerequisites are already present on refactor:

Related Issue

N/A

Documentation PR

N/A - documentation is included.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other

Testing

  • bun test src: 2236 pass, 0 fail
  • focused project/Runtime/Harness invoke suites: 149 pass, 0 fail
  • bun run typecheck
  • bun run lint:check
  • bun run format:check
  • bun run secrets:check
  • bun run build
  • git diff --check

Live verification in account 603141041947, region us-west-2, using the retained InvokeMatrix827 project:

  • Runtime headless invoke omitted --name, preserved the native raw SSE response, and returned REBASED_RUNTIME_OK
  • Harness headless invoke omitted --name, preserved the transcript response, and returned REBASED_HARNESS_OK
  • the 120x40 TUI harness listed the project Runtime and Harness with type, protocol, and source
  • Runtime selection opened the existing endpoint picker and JSON console
  • Harness selection opened the existing chat
  • Escape returned from both embedded consoles to the project picker without leaving the TUI process

Checklist

  • I have added tests that prove the feature works
  • I have updated relevant documentation
  • I have verified direct Runtime and Harness behavior remains green
  • I have run live deployment and TUI verification
  • Dependent changes have been merged and published

@github-actionsgithub-actionsBot added the size/xl PR size: XL label Aug 26, 2026
@agentcore-devx-automationagentcore-devx-automationBot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automationagentcore-devx-automationBot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@codecov-commenter

codecov-commenter commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.56098% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.25%. Comparing base (b18bb4b) to head (98f2da8).
⚠️ Report is 2 commits behind head on refactor.

Files with missing linesPatch %Lines
src/handlers/project/invoke/runtime.tsx97.14%4 Missing ⚠️
src/handlers/project/invoke/selection.ts85.71%4 Missing ⚠️
src/handlers/project/invoke/index.tsx87.50%3 Missing ⚠️
src/handlers/project/invoke/harness.tsx98.36%1 Missing ⚠️
src/handlers/project/invoke/screen.tsx99.17%1 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## refactor #2115 +/- ##
============================================
- Coverage 97.25% 97.25% -0.01% 
============================================
Files 472 479 +7 Lines 29018 29491 +473 ============================================
+ Hits 28221 28681 +460 - Misses 797 810 +13 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@agentcore-devx-automationagentcore-devx-automationBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AgentCore Harness Review

Verdict: Looks good

Nice split: the shared invokeRuntimeTarget / invokeHarnessTurn helpers cleanly refactor the existing handlers into reusable operations, the new project-level invoke composes those without duplication, and the resolveDeployedResource layering (manager → backend → deployment helpers) is easy to follow. Tests use real temp dirs + fake backends, and only mock at true I/O boundaries (readStack, per the guidelines).

One thing worth double-checking before this fully lights up end-to-end:

  • src/core/project/backends/cdk/deployment.ts:28 looks up harnesses by CloudFormation export name ${stackName}-Harness-${resourceName}-Id. Scanning agentcore-l3-cdk-constructs, the harness constructs (AgentCoreHarnessEnvironment, AgentCoreHarnessRole, AgentCoreApplication) currently only emit Harness-<name>-RoleArn and Harness-<name>-ImageUri outputs — no Harness-<name>-Id. Runtime lookup will work today (AgentEnvironment.ts emits <agentName>-RuntimeId), but agentcore invoke --harness ... will always fail with the "not deployed" error until the L3 emits that export. If a coordinated L3 change is in flight this is fine; if not, this handler and its export-name contract will need to land together with the construct change (and ideally the runtime path in AgentEnvironment.ts should probably also be prefixed like -Runtime-<name>-Id for symmetry with Harness-<name>-Id, but that's a naming choice).

Not blocking — tests all pass with a fake backend, and if the harness export is a known follow-up this is just a heads-up. Everything else (validation, mutual-exclusion, --json requiring content, session-id length rule, bearer-token restricted to runtime, TUI launch with inputMode: "prompt", region override from the resolved target) reads correctly.

@agentcore-devx-automationagentcore-devx-automationBot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Aug 26, 2026
@aidandaly24
aidandaly24force-pushed the feat/project-aware-invoke branch from f2c164c to c6796beCompareAugust 26, 2026 22:02
@github-actionsgithub-actionsBot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automationagentcore-devx-automationBot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automationagentcore-devx-automationBot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@github-actionsgithub-actionsBot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automationagentcore-devx-automationBot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automationagentcore-devx-automationBot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@github-actionsgithub-actionsBot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 27, 2026
@agentcore-devx-automationagentcore-devx-automationBot added the claude-security-reviewing Claude Code /security-review in progress label Aug 27, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automationagentcore-devx-automationBot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 27, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@HweinstockHweinstock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks for making this change, I know its a big, but critical one. I honestly didn't get to all of it, but saw a few patterns I wanted to comment on:

  • not all of the invoke runtime logic lives in core, so we end up importing across handlers, and breaking dependency inversion boundary to share this functionality, but it feels like we're fighting the framework/architecture. Might be worth chatting w/ @AlexanderRichey to hear his vision on where this logic should live since he knows it best.
  • the tui being conditionally rendered rather than only on no flags adds a lot of complexity downstream with that launch context being passed around, and I'm wondering if this is required?

qualifier: flags.qualifier,
bearerToken,
};
await renderInvokeTui(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

wouldn't this mean if I do agentcore project invoke --session-id .. --qualifier .. --target .. --bearer-token we would open the TUI?

I thought the convention was that no flags => open TUI.

I'm open to breaking this, but I do think we need to be consistent since it might confuse a customer (or their agent) if it varies by command what determines if a TUI opens.

On the flip side, I do think this existing convention helps keep things simple. For example, we don't need the branching logic here to conditionally render the tui in a few places.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah this is legacy from the old CLI. Runtime and Harness invoke already treat session, qualifier, authentication, and target values as TUI launch configuration. Project invoke is consistent with those commands.

I definitely agree with the concern about the pattern, like you mention. But I also agree with what you say where it keeps things simple. This makes it so that I am able to do things like pass a bearer token or an session id, before i open the TUI. If this wasn't an option we would need to provide a way for the user to do that within the TUI. Which we wanted to avoid for right now.

throw new InputValidationError("--bearer-token is only valid with --runtime");
}
if (
selected.resourceType === "harness" &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

doesn't a similar constraint also apply to runtime (with a higher cap)? https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_InvokeAgentRuntime.html#API_InvokeAgentRuntime_RequestSyntax

unreleated to changes here but I wonder why they are different max length?


function targetContext(ctx: Context, region: string): Context {
return ctx.withValue(RegionKey, region);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the advantage of making this a function? I feel like it adds an unnecessary layer of indirection.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thought I had removed this. Will fix this.

import { argument, createHandler, flag, ProjectKey, type Context } from "../../../router";
import { JsonRendererKey, renderTuiAt } from "../../../tui";
import { RuntimeInvokeLaunchContextKey } from "../../runtime/invoke/launchContext";
import { invokeRuntimeTarget } from "../../runtime/invoke/operation";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this feels strange to me. I'm not sure we want handlers from project depending on imperative handlers. I feel like core should be where this shared functionality lives.

My understanding of the setup was that handlers serve as a "ui shell" over the functionality that handle routing and validation, with core implementing the core logic. However, I think @AlexanderRichey would know better.

@aidandaly24aidandaly24Aug 28, 2026

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, I had the same concern. I extracted these operations because duplicating the Runtime and Harness invocation flows under project felt incorrect. I agree the dependency direction is unusual, though, and invokeRuntimeTarget in particular may belong behind CoreRuntimeClient.

The complication is that the current Runtime operation composes handler-owned request normalization, while the Harness operation folds service events into the handler-owned transcript model. I don’t think source resolution, terminal output, TUI state, or transcript presentation should move into Core, but there
may be a cleaner split where Core owns the Runtime lookup/normalization/invocation workflow and handlers retain presentation policy.

I’d definitely like to check with @AlexanderRichey before changing this too much so we follow the intended architecture

}

if (selected.resourceType === "harness") {
const result = await invokeHarnessTurn(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

where we do handle user cancellations for harness? I see the wrapper for runtime below.

Comment threadREADME.md Outdated
agentcore project invoke

# The project-aware shorthand has the same behavior inside a project.
agentcore invoke

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks for updating the docs!

Also, I like this idea of making it project aware, but I wonder if we should revisit this with all project commands together to make sure the behavior is consistent. If the team has already aligned this is where we're heading than I'm good to leave it in.

Comment threadsrc/errors/errors.test.tsx Outdated
expect(UserCancellationError.resolve(new Error("failed"))).toBeUndefined();
});

test("RuntimeAgentResponseError is a visible service failure", () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: could this be part of the test.each below? Its doing the same thing with one more check for a check for silent, which could be added as a parameter to the tabled test.

ex.

test.each([
...
[
"RuntimeAgentResponseError", new RuntimeAgentResponseError("Model access denied"),
"service", false" // not silent
]
...

Comment threadsrc/core/project/manager.test.ts Outdated
});

describe("FsProjectManager.resolveDeployedResource", () => {
const targets: AwsDeploymentTarget[] = [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

q: what behavior are we testing here, that we don't get through the handlers?

@@ -0,0 +1,125 @@
import { parseAgentEvent } from "../../../core/project/agentEventParser";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

isn't this breaking the dependency inversion?

Comment threadsrc/core/project/agentEventParser.ts Outdated
@@ -0,0 +1,60 @@
export type AgentEvent =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm kind of confused where this fits in. Isn't this assuming a certain response shape from the customer's runtime?

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@AlexanderRicheyAlexanderRichey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How does invoke work today? Do customers have to specify runtime or harness?

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

Labels

size/xlPR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@aidandaly24@codecov-commenter@AlexanderRichey@Hweinstock