Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@brandonskiser
Copy link
Contributor

@brandonskiser brandonskiser commented Oct 10, 2025

Description of changes:

  • Adding a new crate agent that implements the agent config. This crate is based on an actor model where an agent can be interacted with using an AgentHandle, from which messages (send prompt, approve tool use, etc.) are sent and events are received.
  • A minimal run CLI is provided which illustrates the API

This contains substantial code duplication from chat-cli for the API client and database since this was developed in isolation from the rest of the code (see fast follows below).

A lot of this is still WIP, the goal here is to get this pushed and incrementally develop this crate while working on the /delegate tool and overall chat refactor.

Todos (as of now):

  • Implement remote HTTP MCP support
  • Finish built-in tools - fs_read and fs_write, and the experimental tools we have today.
  • Test coverage and validation that the agent spec is fully implemented

There are a lot of details that will be uncovered as more work is done adding this crate to the main chat-cli code base.

Fast Follows:

  • Remove the copied code for the database and API client. Agent would instead just have a Box<dyn Model> passed to it. All of the rts implementation for Model should be moved to chat-cli instead.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@brandonskiser brandonskiser marked this pull request as ready for review October 29, 2025 22:59
Copy link
Contributor

@dingfeli dingfeli left a comment

Choose a reason for hiding this comment

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

LGTM

Comment on lines +120 to +125
agent
.send_prompt(SendPromptArgs {
content: vec![ContentChunk::Text(initial_prompt)],
should_continue_turn: None,
})
.await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we always assume there is an initial prompt?

Comment on lines +191 to +192
print!("{}", text);
let _ = std::io::stdout().flush();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this subject to change? I see here we are just logging to stdout. Is the plan to instead write to some sort of listener that is in charge of eventually displaying it.

///
/// Note that a turn can continue even after a [AgentEvent::Stop] for when the agent encounters
/// an error, and the next prompt chooses to continue the turn.
EndTurn(UserTurnMetadata),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is a request - response considered a user turn?
I see this is referenced in [RunArgs::main_loop], and it looks like this is a condition that would end the execution of main_loop.

Copy link
Contributor

Choose a reason for hiding this comment

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

Though I was only following the code path starting from main.rs. I am guessing that's only one use case (looks like non-interactive?).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A user turn consists of all requests up until either a non-retryable error, or the model responds with no tool uses

}

#[derive(Debug, Clone)]
pub enum McpManagerRequest {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also have a variant for Shutting down server. i.e. during unloading of an agent for example.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nvm, as I had discovered in https://github.com/aws/amazon-q-developer-cli/pull/3150/files#r2479586268, each agent is to have their own McpManager. There is no concept of unloading agent to McpManager since McpManager has the same lifetime as the associated agent.

We wouldn't need a variant for unloading mcp server unless we support hot loading agent config in the future or something.

Comment on lines +171 to +195
tokio::select! {
req = self.request_rx.recv() => {
std::mem::drop(initializing_servers);
std::mem::drop(initialized_servers);
let Some(req) = req else {
warn!("Tool manager request channel has closed, exiting");
break;
};
let res = self.handle_mcp_manager_request(req.payload).await;
respond!(req, res);
},
res = initializing_servers.next(), if !initializing_servers.is_empty() => {
std::mem::drop(initializing_servers);
std::mem::drop(initialized_servers);
if let Some((name, evt)) = res {
self.handle_initializing_mcp_actor_event(name, evt).await;
}
},
res = initialized_servers.next(), if !initialized_servers.is_empty() => {
std::mem::drop(initializing_servers);
std::mem::drop(initialized_servers);
if let Some((name, evt)) = res {
self.handle_mcp_actor_event(name, evt).await;
}
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Would the unordered future not be dropped anyway? Not that there is anything wrong with doing that explicitly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There were borrow checker errors without the explicit drop for some reason - this is an area of the code that could definitely use some testing to ensure no messages are dropped (FuturesUnordered should be cancel safe so long as all of the futures it contains are cancel safe, which they are since mpsc is cancel safe)

I imagine there has to be a cleaner way to do this

}
};

let agent = Agent::new(snapshot, model, McpManager::new().spawn()).await?.spawn();
Copy link
Contributor

Choose a reason for hiding this comment

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

So the paradigm is that each Agent would have its own McpManager?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

An agent has a handle to an MCP manager, meaning that multiple agents could potentially share the same MCP manager

Comment on lines +122 to +126
enum McpServerActorResponse {
Tools(Vec<ToolSpec>),
Prompts(Vec<Prompt>),
ExecuteTool(oneshot::Receiver<ExecuteToolResult>),
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think missing from this is the prompt "hydration" result. Prompt here is just metadata about the prompt. The actual filled in prompt would need its own variant as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What is prompt hydration? If you mean the request that actually expands the prompt, then yeah that wasn't included in this enum yet. It would be the same as the execute tool flow though

#[serde(untagged)]
pub enum McpServerConfig {
Local(LocalMcpServerConfig),
StreamableHTTP(StreamableHTTPMcpServerConfig),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can just name this variant remote (as well as StreamableHTTPMcpServerConfig to just RemoteMcpServerConfig). We won't be differentiating bewteen SSE and Streamable HTTP from the config.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SSE + Streamable have the same exact config structure? Then yeah sounds good.

Comment on lines +244 to +254
pub struct StreamableHTTPMcpServerConfig {
/// The URL endpoint for HTTP-based MCP servers
pub url: String,
/// HTTP headers to include when communicating with HTTP-based MCP servers
#[serde(default)]
pub headers: HashMap<String, String>,
/// Timeout for each mcp request in ms
#[serde(alias = "timeout")]
#[serde(default = "default_timeout")]
pub timeout_ms: u64,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing here is the auth related attributes. I'll add that in once this merges.

@brandonskiser brandonskiser merged commit 4e7974b into main Oct 30, 2025
15 checks passed
@brandonskiser brandonskiser deleted the bskiser/add-agent-crate branch October 30, 2025 22:59
dk19y added a commit that referenced this pull request Nov 4, 2025
* Revert "feat: Updates models to match latest, including endpoint resolver (#3262)" (#3288)

This reverts commit 884b27f.

* chore: bump version to 1.19.2

* fix: racing condition on conduit when printing (#3308)

* chore: version bump to 1.19.3 (#3310)

* refactor: migrate from directories to hierarchical paths module (#3309)

- Replace directories module with new paths module using PathResolver pattern
- Add workspace and global path scopes with clear separation of concerns
- Implement static path methods to avoid circular dependencies in Database/Settings
- Centralize all path constants and patterns in dedicated modules

This refactoring improves path management consistency and provides a cleaner,
more maintainable architecture for handling file system paths throughout
the application.

* Add auth login failure telemetry for cli (#3317)

* add auth login failure telemetry

* fix: expand ~ in prompt file:// URIs (#3301)

* Refactor /Usage into smaller modules (#3324)

Co-authored-by: Akhilesh Bontala <[email protected]>

* feat: add agent crate (#3150)

* refactor: centralize environment variable access (#3315)

* Shim layer for env variable access

* feat: warn when duplicate agents are found during load (#3335)

* Upgrade delegate with better UX for notifications and change the file dependence. (#3337)

* chore: move RTS code from agent crate to chat-cli (#3340)

* fix: block dangerous patterns for tool calls (#3313)

* first commit

* disallowed dangerous patterns as a first priority for executing tools

* recovered hooks help

* got rid of removeme

* got rid of space

* refactored requires_acceptance to ensure correct ordering of safeguards and allowed commands

* formatted for cargo again

* chore: remove duplicate and unused API code from the agent crate (#3342)

* Revert "feat: rebrand paths from .aws/amazonq/ and .amazonq/ to .kiro-cli/"

This reverts commit 44dad82.

* Revert "feat: rebrand environment variables from Q_/AMAZON_Q_ to KIRO_"

This reverts commit 49cbe8e.

---------

Co-authored-by: Brandon Kiser <[email protected]>
Co-authored-by: Brandon Kiser <[email protected]>
Co-authored-by: Felix Ding <[email protected]>
Co-authored-by: abhraina-aws <[email protected]>
Co-authored-by: Jonathan Little <[email protected]>
Co-authored-by: Akhilesh Bontala <[email protected]>
Co-authored-by: Akhilesh Bontala <[email protected]>
Co-authored-by: ekang7 <[email protected]>
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.

2 participants