Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Create a managed Harness project, deploy it, and send a prompt:
agentcore create --name MyAssistant
cd MyAssistant
agentcore deploy
agentcore invoke harness --prompt "Hey, what can you do for me?"
agentcore invoke --harness MyAssistant --prompt "Hey, what can you do for me?"
```

To start with code you own instead, create a Runtime project from a template.
Expand Down Expand Up @@ -64,8 +64,8 @@ agentcore invoke --help
```

Supported bare commands open their interactive flows in a terminal. Operation
flags select headless behavior for most commands. Project invoke commands can
use `--name` and `--target` to select a deployed agent for an interactive session.
flags select headless behavior for most commands. `invoke` can use `--runtime`,
`--harness`, `--gateway`, and `--target` to select a resource for an interactive session.
Run `agentcore create` for guided setup. To create a default project without
the wizard, run `agentcore create --name MyAssistant`.

Expand Down
45 changes: 12 additions & 33 deletions command.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ This reference was generated from `agentcore --help` for version `1.0.0-rc.4`.
- [`agentcore dev`](#agentcore-dev)
- [`agentcore deploy`](#agentcore-deploy)
- [`agentcore invoke`](#agentcore-invoke)
- [`agentcore invoke runtime`](#agentcore-invoke-runtime)
- [`agentcore invoke harness`](#agentcore-invoke-harness)
- [`agentcore log`](#agentcore-log)
- [`agentcore log runtime`](#agentcore-log-runtime)
- [`agentcore log harness`](#agentcore-log-harness)
Expand Down Expand Up @@ -647,58 +645,39 @@ deploy the project to AWS
### `agentcore invoke`

```text
agentcore invoke [options] [command]
agentcore invoke [options]
```

invoke a Runtime or harness from the current project

#### `agentcore invoke runtime`

```text
agentcore invoke runtime [options]
```

invoke a Runtime from the current project
invoke a Runtime, harness, or Gateway

**Options**

- `--name <name>`: the logical project Runtime name
- `--local`: invoke a local Runtime development server (default: false)
- `--port <port>`: local Runtime development server port (defaults: HTTP/AG-UI 8080, MCP 8000, A2A 9000)
- `--target <target>`: project deployment target (default: default)
- `--runtime <runtime>`: the Runtime to invoke: its name in this project, its ID, or its ARN
- `--harness <harness>`: the harness to invoke: its name in this project, its ID, or its ARN
- `--gateway <gateway>`: the Gateway to invoke: its name in this project, its ID, or its ARN
- `--target <target>`: project deployment target (default: "default")
- `--local`: invoke the local development server (project Runtime only) (default: false)
- `--port <port>`: local development server port (defaults: HTTP/AG-UI 8080, MCP 8000, A2A 9000)
- `--payload <payload>`: the inline payload to send
- `--qualifier <qualifier>`: the Runtime endpoint qualifier
- `--content-type <content-type>`: the payload content type
- `--accept <accept>`: the accepted response content type
- `--session-id <session-id>`: the Runtime session ID
- `--user-id <user-id>`: the Runtime user ID (default "default")
- `--header <header...>`: an ordered application header
- `--bearer-token <bearer-token>`: the CUSTOM\_JWT bearer token
- `--mcp-session-id <mcp-session-id>`: the MCP session ID
- `--mcp-protocol-version <mcp-protocol-version>`: the MCP protocol version
- `--output-file <output-file>`: the response output file
- `--user-id <user-id>`: the Runtime user ID (default "default")
- `--mcp-method <mcp-method>`: the MCP method
- `--mcp-name <mcp-name>`: the MCP tool, resource, or prompt name
- `--trace-id <trace-id>`: the X-Ray trace ID
- `--trace-parent <trace-parent>`: the W3C trace parent
- `--trace-state <trace-state>`: the W3C trace state
- `--baggage <baggage>`: the W3C baggage
- `--output-file <output-file>`: the response output file

#### `agentcore invoke harness`

```text
agentcore invoke harness [options]
```

invoke a harness from the current project

**Options**

- `--name <name>`: the logical project harness name
- `--target <target>`: project deployment target (default: "default")
- `--prompt <prompt>`: the message to send to the harness
- `--session-id <session-id>`: the Runtime session ID to continue (33-100 characters)
- `--qualifier <qualifier>`: the harness endpoint qualifier to invoke (default DEFAULT)
- `--path <path>`: the path relative to the Gateway origin
- `--method <method>`: the HTTP request method

### `agentcore log`

Expand Down
8 changes: 3 additions & 5 deletions e2eTest/project/templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,9 @@ describe(
await cli.run(
[
"invoke",
"runtime",
"--local",
"--name",
"--runtime",
runtime.name,
"--local",
"--port",
String(port),
"--session-id",
Expand Down Expand Up @@ -288,8 +287,7 @@ describe(
await cli.run(
[
"invoke",
"runtime",
"--name",
"--runtime",
runtime.name,
"--session-id",
sessionId,
Expand Down
4 changes: 2 additions & 2 deletions src/assets/templates/agent-python-langchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Run the agent locally from the project root:

```bash
agentcore dev
agentcore invoke runtime --local --name {{name}} --payload '{"prompt":"What is 2 plus 3?"}'
agentcore invoke --runtime {{name}} --local --payload '{"prompt":"What is 2 plus 3?"}'
```

Environment variables for local development go in `agentcore/.env.local`
Expand All @@ -32,7 +32,7 @@ Environment variables for local development go in `agentcore/.env.local`

```bash
agentcore deploy
agentcore invoke runtime --payload '{"prompt":"Hello!"}'
agentcore invoke --runtime {{name}} --payload '{"prompt":"Hello!"}'
```

Traces are collected automatically: AgentCore Runtime starts the agent under
Expand Down
2 changes: 1 addition & 1 deletion src/assets/templates/agent-python-minimal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ Environment variables for local development go in `agentcore/.env.local`

```bash
agentcore deploy
agentcore invoke runtime --payload '{"prompt":"Hello!"}'
agentcore invoke --runtime {{name}} --payload '{"prompt":"Hello!"}'
```
2 changes: 1 addition & 1 deletion src/assets/templates/agent-python-strands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,5 @@ After providing credentials, `agentcore deploy` will deploy your project into Am
Invoke the deployed Runtime with its native payload:

```bash
agentcore invoke runtime --payload '{"prompt":"Hello!"}'
agentcore invoke --runtime {{name}} --payload '{"prompt":"Hello!"}'
```
2 changes: 1 addition & 1 deletion src/assets/templates/agent-typescript-strands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ After providing credentials, `agentcore deploy` will deploy your project into Am
Invoke the deployed Runtime with its native payload:

```bash
agentcore invoke runtime --payload '{"prompt":"Hello!","actorId":"user-123"}'
agentcore invoke --runtime {{runtimeName}} --payload '{"prompt":"Hello!","actorId":"user-123"}'
```
2 changes: 1 addition & 1 deletion src/assets/templates/agui-python-strands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ health at `http://127.0.0.1:8080/ping`.
runtime with an AG-UI `RunAgentInput` payload:

```bash
agentcore invoke runtime --name {{ name }} \
agentcore invoke --runtime {{ name }} \
--payload '{"threadId":"t1","runId":"r1","state":{},"messages":[{"id":"m1","role":"user","content":"Hello!"}],"tools":[],"context":[],"forwardedProps":{}}'
```

Expand Down
2 changes: 1 addition & 1 deletion src/assets/templates/export-harness-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ After providing credentials, `agentcore deploy` will deploy your project into Am
Invoke the deployed Runtime with its native payload:

```bash
agentcore invoke runtime --payload '{"prompt":"Hello!"}'
agentcore invoke --runtime {{name}} --payload '{"prompt":"Hello!"}'
```
2 changes: 1 addition & 1 deletion src/assets/templates/mcp-python-fastmcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ sending JSON-RPC to `http://127.0.0.1:8000/mcp`.
## Deployment

`agentcore deploy` deploys the server into Amazon Bedrock AgentCore. Invoke it with
`agentcore invoke runtime`, supplying an MCP JSON-RPC payload (e.g. `tools/list`, `tools/call`).
`agentcore invoke --runtime {{name}}`, supplying an MCP JSON-RPC payload (e.g. `tools/list`, `tools/call`).
12 changes: 12 additions & 0 deletions src/core/project/backends/cdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,7 @@ describe("CdkBackend.resolveDeployedResources", () => {
},
],
harnesses: [{ name: "support_agent", path: "app/support_agent" }],
agentCoreGateways: [{ name: "tools-gateway", targets: [] }],
});
await updateTargetState(json, input.rootPath, TARGET.name, { stackArn: STACK_ARN });
const subject = harness({
Expand All @@ -1031,6 +1032,10 @@ describe("CdkBackend.resolveDeployedResources", () => {
ExportName: "AgentCore-example-default-Harness-support-agent-Id",
OutputValue: "support_agent-AbCdEf1234",
},
{
ExportName: "AgentCore-example-default-Gateway-tools-gateway-Id",
OutputValue: "tools-gateway-abcdef1234",
},
],
},
});
Expand All @@ -1052,6 +1057,13 @@ describe("CdkBackend.resolveDeployedResources", () => {
target: TARGET,
credentialProvider: subject.credentials,
},
{
resourceType: "gateway",
name: "tools-gateway",
id: "tools-gateway-abcdef1234",
target: TARGET,
credentialProvider: subject.credentials,
},
]);
expect(subject.stackReads).toHaveLength(1);
});
Expand Down
13 changes: 9 additions & 4 deletions src/core/project/backends/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ function findDeployedResourceId(
): string | undefined {
if (!stack.StackName) return undefined;
const exportResourceName = input.name.replaceAll("_", "-");
const exportName =
input.resourceType === "runtime"
? `${stack.StackName}-${exportResourceName}-RuntimeId`
: `${stack.StackName}-Harness-${exportResourceName}-Id`;
const exportName = {
runtime: `${stack.StackName}-${exportResourceName}-RuntimeId`,
harness: `${stack.StackName}-Harness-${exportResourceName}-Id`,
gateway: `${stack.StackName}-Gateway-${exportResourceName}-Id`,
}[input.resourceType];
return stack.Outputs?.find((output) => output.ExportName === exportName)?.OutputValue;
}

Expand Down Expand Up @@ -506,6 +507,10 @@ export class CdkBackend implements ProjectBackend {
const resources = [
...project.spec.runtimes.map(({ name }) => ({ resourceType: "runtime" as const, name })),
...project.spec.harnesses.map(({ name }) => ({ resourceType: "harness" as const, name })),
...project.spec.agentCoreGateways.map(({ name }) => ({
resourceType: "gateway" as const,
name,
})),
];
return resources.flatMap((resource) => {
const id = findDeployedResourceId(stack, resource);
Expand Down
9 changes: 5 additions & 4 deletions src/core/project/manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
RemoveResourceResult,
RemoveResourcesResult,
} from "../../handlers/project/types";
import { RESOURCE_LABELS } from "../../handlers/project/types";
import type { Logger } from "../../logging";
import {
FsReadWriteJson,
Expand Down Expand Up @@ -1044,12 +1045,12 @@ export class FsProjectManager implements ProjectManager {
({ resourceType, name }) => resourceType === input.resourceType && name === input.name,
);
// The declared target wins over the copy on the item: the manager resolved it
// from aws-targets.json, and both invoke handlers pin the AWS region from this
// value while reusing the backend's verified credential provider. Trusting a
// backend's target echo would let it redirect the call.
// from aws-targets.json, and the invoke, log, and traces handlers pin the AWS
// region from this value while reusing the backend's verified credential
// provider. Trusting a backend's target echo would let it redirect the call.
if (resource) return { ...resource, target: resolved.target };

const label = input.resourceType === "runtime" ? "Runtime" : "Harness";
const label = RESOURCE_LABELS[input.resourceType];
throw new ProjectStateError(
`${label} '${input.name}' is not deployed to target '${input.target}'. ` +
`Run 'agentcore deploy --target ${input.target}' first.`,
Expand Down
7 changes: 6 additions & 1 deletion src/core/project/templates/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa
const tree = await FsTreeNode.fromAssetSource(
{ assetSource },
{ assetDir: "templates/agent-python-minimal" },
{ rootDirName: input.name },
{
rootDirName: input.name,
transformContent: (raw) =>
templateRenderer.render(raw, { name: toPythonPackageName(input.name) }),
},
);
return { tree, spec: { runtimes: [buildRuntimeSpec(input)] } };
},
Expand Down Expand Up @@ -186,6 +190,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa
const modelScaffold = resolveModelProviderScaffold(input);
const context = {
name: toNpmPackageName(input.name),
runtimeName: input.name,
memoryEnvVarName: memory ? memoryEnvVarName(memory.name) : undefined,
...modelScaffold.templateRenderContext,
};
Expand Down
56 changes: 29 additions & 27 deletions src/handlers/gateway/invoke/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,34 @@ import {
import { writeGatewayInvokeResponse } from "./response";
import { GatewayInvokeLaunchContextKey } from "./launchContext";

export const invokeGatewayFlags = [
flag("id", "the ID of the Gateway", gatewayIdSchema),
flag(
"path",
"the path relative to the Gateway origin",
z.string().min(1, "requires a nonempty path").optional(),
{ sensitive: true },
),
flag("method", "the HTTP request method", z.enum(["GET", "POST", "DELETE"]).optional()),
flag("payload", "the inline payload to send", z.string().optional(), { sensitive: true }),
flag("content-type", "the payload content type", z.string().optional()),
flag("accept", "the accepted response content type", z.string().optional()),
flag("header", "an ordered application header", z.array(z.string()).optional(), {
sensitive: true,
}),
flag("bearer-token", "the Gateway bearer token", z.string().optional(), {
sensitive: true,
}),
flag("session-id", "the Runtime target session ID", z.string().optional()),
flag("mcp-session-id", "the MCP session ID", z.string().optional()),
flag("mcp-protocol-version", "the MCP protocol version", z.string().optional()),
flag(
"output-file",
"the response output file",
z.string().min(1, "requires a nonempty path").optional(),
),
] as const;

export const createInvokeGatewayHandler = (
core: Core,
io: AppIO,
Expand All @@ -27,33 +55,7 @@ export const createInvokeGatewayHandler = (
createHandler({
name: "invoke",
description: "invoke an AgentCore Gateway",
flags: [
flag("id", "the ID of the Gateway", gatewayIdSchema),
flag(
"path",
"the path relative to the Gateway origin",
z.string().min(1, "requires a nonempty path").optional(),
{ sensitive: true },
),
flag("method", "the HTTP request method", z.enum(["GET", "POST", "DELETE"]).optional()),
flag("payload", "the inline payload to send", z.string().optional(), { sensitive: true }),
flag("content-type", "the payload content type", z.string().optional()),
flag("accept", "the accepted response content type", z.string().optional()),
flag("header", "an ordered application header", z.array(z.string()).optional(), {
sensitive: true,
}),
flag("bearer-token", "the Gateway bearer token", z.string().optional(), {
sensitive: true,
}),
flag("session-id", "the Runtime target session ID", z.string().optional()),
flag("mcp-session-id", "the MCP session ID", z.string().optional()),
flag("mcp-protocol-version", "the MCP protocol version", z.string().optional()),
flag(
"output-file",
"the response output file",
z.string().min(1, "requires a nonempty path").optional(),
),
],
flags: invokeGatewayFlags,
handle: async (ctx, flags) => {
const jsonOutput = ctx.require(JsonKey);
if (flags.payload === undefined) {
Expand Down
10 changes: 9 additions & 1 deletion src/handlers/gateway/invoke/screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,16 @@ export function GatewayInvokeScreen(props: ScreenProps) {
type GatewayInvokeConsoleProps = ScreenProps & {
gatewayId: string;
initialContext?: GatewayInvokeLaunchContext;
onBack?: () => void;
};

function GatewayInvokeConsole({ ctx, core, gatewayId, initialContext }: GatewayInvokeConsoleProps) {
export function GatewayInvokeConsole({
ctx,
core,
gatewayId,
initialContext,
onBack,
}: GatewayInvokeConsoleProps) {
const navigate = useNavigate();
const opts = coreOptsFromCtx(ctx);
const { columns, rows } = useWindowSize();
Expand Down Expand Up @@ -385,6 +392,7 @@ function GatewayInvokeConsole({ ctx, core, gatewayId, initialContext }: GatewayI
}
if (key.escape) {
if (abortRef.current) abortRef.current.abort();
else if (onBack) onBack();
else navigate(invokePath());
return;
}
Expand Down
Loading
Loading