Skip to content

Commit daf5bb2

Browse files
committed
feat(dev): add positional prompt arg, remove --invoke flag
Replace `agentcore dev --invoke "Hello"` with `agentcore dev "Hello"`. The dev command now accepts an optional positional [prompt] argument that invokes a running dev server directly. The --invoke/-i flag is removed entirely — this is a breaking change for scripts using it. Rejected: keep --invoke as deprecated alias | adds UX confusion with two ways to do the same thing Confidence: high Scope-risk: narrow
1 parent 5e0f584 commit daf5bb2

5 files changed

Lines changed: 69 additions & 36 deletions

File tree

docs/commands.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -475,22 +475,23 @@ Start local development server with hot-reload.
475475
agentcore dev
476476
agentcore dev --agent MyAgent --port 3000
477477
agentcore dev --logs # Non-interactive
478-
agentcore dev --invoke "Hello" --stream # Direct invoke
478+
agentcore dev "Hello" --stream # Invoke running server
479+
agentcore dev "Hello" --agent MyAgent # Invoke specific agent
479480

480481
# MCP protocol dev commands
481-
agentcore dev --invoke list-tools
482-
agentcore dev --invoke call-tool --tool myTool --input '{"arg": "value"}'
482+
agentcore dev list-tools
483+
agentcore dev call-tool --tool myTool --input '{"arg": "value"}'
483484
```
484485

485-
| Flag | Description |
486-
| ----------------------- | ------------------------------------------------------ |
487-
| `-p, --port <port>` | Port (default: 8080; MCP uses 8000, A2A uses 9000) |
488-
| `-a, --agent <name>` | Agent to run (required if multiple agents) |
489-
| `-i, --invoke <prompt>` | Invoke running server |
490-
| `-s, --stream` | Stream response (with --invoke) |
491-
| `-l, --logs` | Non-interactive stdout logging |
492-
| `--tool <name>` | MCP tool name (with `--invoke call-tool`) |
493-
| `--input <json>` | MCP tool arguments as JSON (with `--invoke call-tool`) |
486+
| Flag / Argument | Description |
487+
| -------------------- | ---------------------------------------------------- |
488+
| `[prompt]` | Invoke running dev server with this prompt |
489+
| `-p, --port <port>` | Port (default: 8080; MCP uses 8000, A2A uses 9000) |
490+
| `-a, --agent <name>` | Agent to run or invoke (required if multiple agents) |
491+
| `-s, --stream` | Stream response when invoking |
492+
| `-l, --logs` | Non-interactive stdout logging |
493+
| `--tool <name>` | MCP tool name (with `call-tool` prompt) |
494+
| `--input <json>` | MCP tool arguments as JSON (with `--tool`) |
494495

495496
### invoke
496497

docs/local-development.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,14 @@ agentcore dev --logs
2323
With the dev server running, open another terminal:
2424

2525
```bash
26-
# Interactive chat
27-
agentcore invoke
28-
2926
# Single prompt
30-
agentcore invoke "What can you do?"
27+
agentcore dev "What can you do?"
3128

3229
# With streaming
33-
agentcore invoke "Tell me a story" --stream
30+
agentcore dev "Tell me a story" --stream
3431

35-
# Direct invoke to running server
36-
agentcore dev --invoke "Hello" --stream
32+
# Specify agent (if multiple)
33+
agentcore dev "Hello" --agent MyAgent
3734
```
3835

3936
## Environment Setup

src/cli/commands/dev/__tests__/dev.test.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@ describe('dev command', () => {
77
const result = await runCLI(['dev', '--help'], process.cwd());
88

99
expect(result.exitCode).toBe(0);
10+
expect(result.stdout.includes('[prompt]'), 'Should show [prompt] positional argument').toBeTruthy();
1011
expect(result.stdout.includes('--port'), 'Should show --port option').toBeTruthy();
1112
expect(result.stdout.includes('--agent'), 'Should show --agent option').toBeTruthy();
12-
expect(result.stdout.includes('--invoke'), 'Should show --invoke option').toBeTruthy();
1313
expect(result.stdout.includes('--stream'), 'Should show --stream option').toBeTruthy();
1414
expect(result.stdout.includes('--logs'), 'Should show --logs option').toBeTruthy();
1515
expect(result.stdout.includes('8080'), 'Should show default port').toBeTruthy();
1616
});
17+
18+
it('does not show --invoke flag', async () => {
19+
const result = await runCLI(['dev', '--help'], process.cwd());
20+
21+
expect(result.exitCode).toBe(0);
22+
expect(result.stdout.includes('--invoke'), 'Should not show removed --invoke option').toBeFalsy();
23+
});
1724
});
1825

1926
describe('requires project context', () => {
@@ -28,6 +35,34 @@ describe('dev command', () => {
2835
});
2936
});
3037

38+
describe('positional prompt invoke', () => {
39+
it('attempts invoke when positional prompt is provided', async () => {
40+
// With no dev server running, the invoke path triggers a connection error
41+
const result = await runCLI(['dev', 'Hello agent'], process.cwd());
42+
43+
expect(result.exitCode).toBe(1);
44+
// Should attempt to connect to dev server and fail — not show a project error
45+
const output = result.stderr.toLowerCase();
46+
expect(
47+
output.includes('fetch failed') || output.includes('econnrefused') || output.includes('dev server not running'),
48+
`Should attempt invoke and fail with connection error, got: ${result.stderr}`
49+
).toBeTruthy();
50+
});
51+
52+
it('does not require project context when invoking', async () => {
53+
// Invoke path loads config but does not call requireProject()
54+
// So the error should be about connection, not missing project
55+
const result = await runCLI(['dev', 'test prompt'], process.cwd());
56+
57+
expect(result.exitCode).toBe(1);
58+
const output = result.stderr.toLowerCase();
59+
expect(
60+
!output.includes('no agentcore project found'),
61+
`Should not fail with project error when prompt is provided, got: ${result.stderr}`
62+
).toBeTruthy();
63+
});
64+
});
65+
3166
describe('flag validation', () => {
3267
it('rejects invalid port number', async () => {
3368
const result = await runCLI(['dev', '--port', 'abc'], process.cwd());
@@ -46,7 +81,6 @@ describe('dev command', () => {
4681

4782
expect(result.exitCode).toBe(0);
4883
expect(result.stdout.includes('--stream'), 'Should show --stream option').toBeTruthy();
49-
expect(result.stdout.includes('--invoke'), 'Should show --invoke option').toBeTruthy();
5084
});
5185
});
5286
});

src/cli/commands/dev/command.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ async function handleMcpInvoke(
9696
}
9797
} else if (invokeValue === 'call-tool') {
9898
if (!toolName) {
99-
console.error('Error: --tool is required with --invoke call-tool');
100-
console.error('Usage: agentcore dev --invoke call-tool --tool <name> --input \'{"arg": "value"}\'');
99+
console.error('Error: --tool is required with call-tool');
100+
console.error('Usage: agentcore dev call-tool --tool <name> --input \'{"arg": "value"}\'');
101101
process.exit(1);
102102
}
103103
// Initialize session first, then call tool with the session ID
@@ -117,8 +117,8 @@ async function handleMcpInvoke(
117117
} else {
118118
console.error(`Error: Unknown MCP invoke command "${invokeValue}"`);
119119
console.error('Usage:');
120-
console.error(' agentcore dev --invoke list-tools');
121-
console.error(' agentcore dev --invoke call-tool --tool <name> --input \'{"arg": "value"}\'');
120+
console.error(' agentcore dev list-tools');
121+
console.error(' agentcore dev call-tool --tool <name> --input \'{"arg": "value"}\'');
122122
process.exit(1);
123123
}
124124
} catch (err) {
@@ -137,20 +137,20 @@ export const registerDev = (program: Command) => {
137137
.command('dev')
138138
.alias('d')
139139
.description(COMMAND_DESCRIPTIONS.dev)
140+
.argument('[prompt]', 'Invoke running dev server with this prompt [non-interactive]')
140141
.option('-p, --port <port>', 'Port for development server', '8080')
141142
.option('-a, --agent <name>', 'Agent to run or invoke (required if multiple agents)')
142-
.option('-i, --invoke <prompt>', 'Invoke running dev server (use --agent if multiple) [non-interactive]')
143-
.option('-s, --stream', 'Stream response when using --invoke [non-interactive]')
143+
.option('-s, --stream', 'Stream response when invoking [non-interactive]')
144144
.option('-l, --logs', 'Run dev server with logs to stdout [non-interactive]')
145-
.option('--tool <name>', 'MCP tool name (used with --invoke call-tool) [non-interactive]')
146-
.option('--input <json>', 'MCP tool arguments as JSON (used with --invoke call-tool) [non-interactive]')
145+
.option('--tool <name>', 'MCP tool name (used with "call-tool" prompt) [non-interactive]')
146+
.option('--input <json>', 'MCP tool arguments as JSON (used with --tool) [non-interactive]')
147147
.option(
148148
'-H, --header <header>',
149149
'Custom header to forward to the agent (format: "Name: Value", repeatable) [non-interactive]',
150150
(val: string, prev: string[]) => [...prev, val],
151151
[] as string[]
152152
)
153-
.action(async opts => {
153+
.action(async (positionalPrompt: string | undefined, opts) => {
154154
try {
155155
const port = parseInt(opts.port, 10);
156156

@@ -160,8 +160,9 @@ export const registerDev = (program: Command) => {
160160
headers = parseHeaderFlags(opts.header);
161161
}
162162

163-
// If --invoke provided, call the dev server and exit
164-
if (opts.invoke) {
163+
// If a prompt is provided, call the dev server and exit
164+
const invokePrompt = positionalPrompt;
165+
if (invokePrompt) {
165166
const invokeProject = await loadProjectConfig(getWorkingDirectory());
166167

167168
// Determine which agent/port to invoke
@@ -190,11 +191,11 @@ export const registerDev = (program: Command) => {
190191

191192
// Protocol-aware dispatch
192193
if (protocol === 'MCP') {
193-
await handleMcpInvoke(invokePort, opts.invoke, opts.tool, opts.input, headers);
194+
await handleMcpInvoke(invokePort, invokePrompt, opts.tool, opts.input, headers);
194195
} else if (protocol === 'A2A') {
195-
await invokeA2ADevServer(invokePort, opts.invoke, headers);
196+
await invokeA2ADevServer(invokePort, invokePrompt, headers);
196197
} else {
197-
await invokeDevServer(invokePort, opts.invoke, opts.stream ?? false, headers);
198+
await invokeDevServer(invokePort, invokePrompt, opts.stream ?? false, headers);
198199
}
199200
return;
200201
}

src/cli/tui/copy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const COMMAND_DESCRIPTIONS = {
3232
add: 'Add resources (agent, evaluator, online-eval, memory, credential, target)',
3333
create: 'Create a new AgentCore project',
3434
deploy: 'Deploy project infrastructure to AWS via CDK.',
35-
dev: 'Launch local development server with hot-reload.',
35+
dev: 'Launch local dev server, or invoke a running one.',
3636
invoke: 'Invoke a deployed agent endpoint.',
3737
logs: 'Stream or search agent runtime logs.',
3838
package: 'Package agent artifacts without deploying.',

0 commit comments

Comments
 (0)