Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basis for named agents #525

Merged
merged 11 commits into from
Jan 1, 2025
Merged

Basis for named agents #525

merged 11 commits into from
Jan 1, 2025

Conversation

zakiali
Copy link
Collaborator

@zakiali zakiali commented Dec 26, 2024

This PR adds a framework for named agents and exposes them in the goose-cli and the goose-server. This PR adds:

  1. An Agent trait that agent versions need to implement. The trait itself has default implementations for most methods. Moved original implementation of Agent to BaseAgent (base.rs) and example of a v1 agent (does nothing/raises an error)
  2. Agent factory for registering and instantiating named agents
  3. Updated goose-cli to be able to set named agents on cli and moved away from the Agent implementation in the cli.
  4. Updated goose-server to be able to set/start named agents and provided an endpoint to get current and available versions

Copy link

Desktop App for this PR

The following build is available for testing:

The app is signed and notarized for macOS. After downloading, unzip the file and drag the Goose.app to your Applications folder.

This link is provided by nightly.link and will work even if you're not logged into GitHub.

Copy link

Desktop App for this PR

The following build is available for testing:

The app is signed and notarized for macOS. After downloading, unzip the file and drag the Goose.app to your Applications folder.

This link is provided by nightly.link and will work even if you're not logged into GitHub.

Copy link

Desktop App for this PR

The following build is available for testing:

The app is signed and notarized for macOS. After downloading, unzip the file and drag the Goose.app to your Applications folder.

This link is provided by nightly.link and will work even if you're not logged into GitHub.

Copy link

Desktop App for this PR

The following build is available for testing:

The app is signed and notarized for macOS. After downloading, unzip the file and drag the Goose.app to your Applications folder.

This link is provided by nightly.link and will work even if you're not logged into GitHub.

@michaelneale
Copy link
Collaborator

@zakiali can you share any docs on named agents that can share around? as I haven't been keeping up !

@zakiali zakiali changed the base branch from v1.0 to v1.0-mcp December 30, 2024 22:05
Copy link
Collaborator

@baxen baxen left a comment

Choose a reason for hiding this comment

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

Looks good! The registry makes a lot of sense, and excited to have multiple versions to test against each other. Left a refactor suggestion for the interface

fn get_provider_usage(&self) -> &Mutex<Vec<ProviderUsage>>;

/// Setup the next inference by budgeting the context window
async fn prepare_inference(
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: i wouldn't leave this as part of the trait i think? although its pretty generally useful agreed, its a private method and i could see an agent taking a different approach

}

/// Create a stream that yields each message as it's generated
async fn reply(&self, messages: &[Message]) -> Result<BoxStream<'_, Result<Message>>> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: i'd probably leave this unimplemented, wdyt? it's nice to reuse here but changes to how this works are the main difference between different agent implementations

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

+1 to this and the previous comment. these are def the meat of the agents and will have different implementations between versions


/// Core trait defining the behavior of an Agent
#[async_trait]
pub trait Agent: Send + Sync {
Copy link
Collaborator

Choose a reason for hiding this comment

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

(a couple of related comments elsewhere)

I'd suggest a refactor here, where we make this interface only expose the client facing methods:

pub async fn reply // core reply loop
pub async fn add_system // connect to or spawn an MCP server via a spec
pub async fn remove_system // remove a system by name
pub async fn list_systems // get status of each system
pub async fn passthrough // pass through a json rpc to a system

and then all the other stuff becomes part of the implementation. But to make that easy/reusable, i'd move all the system management/helper methods onto a new struct, maybe MCPManager or something like that. And then each struct that implements Agent would most likely (but not have to) use that to do the heavy lifting

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Refactored, but ended up adding a usage method as well since we use it in cli and was kind of awkward to add it on to the manager (which implements the logic).

_pending: &[Message],
_target_limit: usize,
) -> AgentResult<Vec<Message>> {
todo!();
Copy link
Collaborator

Choose a reason for hiding this comment

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

i don't understand this part. wouldn't reply() fail since this isn't implemented?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yea, this v1 was an example and just wanted something that would error out quickly when testing things out. I'll remove the v1 implementation before merging

Copy link
Collaborator

Choose a reason for hiding this comment

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

ahh got it

}

#[async_trait]
impl Agent for BaseAgent {
Copy link
Collaborator

@salman1993 salman1993 Dec 31, 2024

Choose a reason for hiding this comment

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

nit: i found this hard to understand, probably cause i was thinking "base" -> "base class" in python. for a while i was thinking Agent depends on BaseAgent lol

since its an implementation of the Agent trait, maybe we use AgentImpl or AgentImplDefault?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What about DefaultAgent instead of BaseAgent? The Impl in the names confuses me a bit, but if that's standard in Rust, happy to do that

Copy link
Collaborator

Choose a reason for hiding this comment

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

i like DefaultAgent

Copy link
Collaborator

@baxen baxen left a comment

Choose a reason for hiding this comment

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

Looks great!!

@zakiali zakiali merged commit 5856a3f into v1.0-mcp Jan 1, 2025
baxen pushed a commit that referenced this pull request Jan 6, 2025
baxen pushed a commit that referenced this pull request Jan 6, 2025
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.

4 participants