rig icon indicating copy to clipboard operation
rig copied to clipboard

feat: Provide a unified interface for creating Agent object

Open AspadaX opened this issue 10 months ago • 4 comments

  • [X] I have looked for existing issues (including closed) about this

Feature Request

Provide a unified LLM interface, or respect the CompletionModel in the crate wide.

Motivation

I am developing a CLI that translates natural languages into executable commands. I would like to integrate multiple providers into the CLI, but the problem I am facing is that rig seems to have different implementations for Agent<M> and making creating a unified interface difficult. Here is a sample code for your references:

pub fn get_client() -> Result<Agent<impl CompletionModel>, Error> {
    let model = std::env::var("MODEL")?;
    
    if model != "" {
        if let Ok(client) = std::panic::catch_unwind(|| {providers::openai::Client::from_env()}) {
            return Ok(client.agent(&model).build());
        }
        
        if let Ok(client) = std::panic::catch_unwind(|| {providers::anthropic::Client::from_env()}) {
            return Ok(client.agent(&model).build());
        }
    }
    
    Ok(())
}

In this case, the compiler will report error if I return a different provider's Agent. Maybe the trait, CompletionModel should be respected across the crate?

Proposal

Maybe respect the trait in the crate wide?

Alternatives

I haven't seen it in the issues yet.

AspadaX avatar Mar 26 '25 05:03 AspadaX

Hi, yes definitely! We have brought this up internally before but perhaps a more generic implementation for this might be more helpful.

joshua-mo-143 avatar Mar 26 '25 13:03 joshua-mo-143

Hi, yes definitely! We have brought this up internally before but perhaps a more generic implementation for this might be more helpful.

That's great! How can I help? I'm developing an open-source CLI tool and want to integrate rig instead of building one from scratch.

AspadaX avatar Mar 27 '25 01:03 AspadaX

At the moment, I think the best way to probably go about this would be to have a simple Client trait:

trait ProviderClient {
    fn from_env() -> Self;
    fn new(api_key: &str) -> Self;
    // .. whatever other methods are required
}

We could probably then just have the other methods as provided methods since most of them are pretty much the same, anyway.

@0xMochan @cvauclair wdyt?

joshua-mo-143 avatar Apr 02 '25 12:04 joshua-mo-143

Hi @AspadaX - rig 0.13.0 includes a way to use polymorphic clients through DynClientBuilder. You can find more about it here: https://docs.rig.rs/docs/concepts/provider_clients

I'm closing this issue for now as it has been solved by #440

joshua-mo-143 avatar Jun 19 '25 23:06 joshua-mo-143