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
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ agentcore # interactive TUI
├── runtime # inspect deployed AgentCore Runtimes
│ ├── get # fetch a Runtime by id
│ ├── list # list Runtimes (server-side paginated)
│ ├── invoke # invoke a Runtime
│ ├── version
│ │ ├── get # get a specific Runtime version
│ │ └── list # list a Runtime's versions
Expand Down Expand Up @@ -154,6 +155,85 @@ Source-aware values: any field flag documented as such accepts the value inline,
`file://` convention). A command reads stdin from at most one flag. For example,
`--instructions file://order-quality.txt` or `--instructions -`.

### Invoke a Runtime

Runtime invocation accepts inline, file, or stdin payload bytes:

```bash
# Inline
agentcore runtime invoke \
--id <runtimeId> \
--payload '{"action":"status"}' \
--content-type application/json \
--accept text/event-stream

# File
agentcore runtime invoke --id <runtimeId> --payload file://request.json

# stdin
cat request.json | agentcore runtime invoke --id <runtimeId> --payload -
```

CUSTOM_JWT Runtimes require `--bearer-token`. The token accepts the same inline,
`file://`, or stdin sources as the payload; payload and token cannot both read
stdin.

```bash
agentcore runtime invoke \
--id <runtimeId> \
--payload file://request.json \
--bearer-token file://$HOME/.config/agentcore/runtime-token
```

For MCP Runtimes, initialize first, then pass the returned Runtime and MCP
session IDs to later methods. MCP requests accept both JSON and SSE responses.

```bash
agentcore runtime invoke \
--id <runtimeId> \
--payload '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"agentcore-cli","version":"1"}}}' \
--accept 'application/json, text/event-stream' \
--mcp-protocol-version 2025-03-26 \
--mcp-method initialize

agentcore runtime invoke \
--id <runtimeId> \
--payload '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
--accept 'application/json, text/event-stream' \
--session-id <returnedRuntimeSessionId> \
--mcp-session-id <returnedMcpSessionId> \
--mcp-protocol-version 2025-03-26 \
--mcp-method tools/list
```

Raw stdout always streams exact response bytes as they arrive, regardless of
content type. `--output-file` streams the same bytes directly to disk. Binary or
unknown responses require `--output-file` or `--json` when stdout is a terminal.
Response metadata is written to stderr.

`--json` buffers the complete response, including streaming representations, and
emits one metadata envelope without interpreting the customer body. If a raw or
file response fails, bytes already written remain available and the stderr
summary reports `complete=false`. A failed JSON response emits no partial
envelope.

```bash
agentcore runtime invoke \
--id <runtimeId> \
--payload file://request.bin \
--content-type application/octet-stream \
--accept application/octet-stream \
--output-file response.bin

agentcore runtime invoke --id <runtimeId> --payload '{"action":"status"}' --json
# {"statusCode":200,"contentType":"application/json","bodyEncoding":"utf8","body":"{\"ok\":true}","complete":true}
```

Runtime Invoke accepts Runtime IDs from the current account only. It does not
accept ARNs, `--version`, `--interactive`, cross-account targets, or custom
request paths. All requests use the Runtime `/invocations` route, including MCP
Runtimes.

Bare Runtime branches and leaves require a TTY on stdin and stdout. Supplying
operation flags runs the command headlessly, and `--json` always suppresses TUI
rendering.
Expand Down
146 changes: 125 additions & 21 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"typescript": "^5"
},
"dependencies": {
"@aws-sdk/client-bedrock-agentcore": "^3.1079.0",
"@aws-sdk/client-bedrock-agentcore": "^3.1092.0",
"@aws-sdk/client-bedrock-agentcore-control": "^3.1079.0",
"@aws-sdk/client-iam": "^3.1080.0",
"@inkui-cli/data-table": "^0.2.0",
Expand Down
32 changes: 32 additions & 0 deletions src/core/abortable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Relays `source` while making an in-flight read reject as soon as `signal` aborts.
*
* Aborts use `signal.reason` or an `AbortError` fallback. The rejection remains
* observed when no read is pending, and source cleanup is fire-and-forget because
* a stalled stream may also stall `iterator.return()`.
*/
export async function* abortable<T>(
source: AsyncIterable<T>,
signal: AbortSignal,
): AsyncGenerator<T> {
let abort = () => {};
const aborted = new Promise<never>((_, reject) => {
abort = () =>
reject(signal.reason ?? new DOMException("The operation was aborted", "AbortError"));
if (signal.aborted) abort();
else signal.addEventListener("abort", abort, { once: true });
});
aborted.catch(() => {});

const iterator = source[Symbol.asyncIterator]();
try {
for (;;) {
const result = await Promise.race([iterator.next(), aborted]);
if (result.done) return;
yield result.value;
}
} finally {
signal.removeEventListener("abort", abort);
void iterator.return?.()?.catch(() => {});
}
}
Loading
Loading