Pular para o conteúdo

State

Registre uma dependência uma vez com .state(value) e peça por ela pelo tipo:

use carmy::prelude::*;
#[derive(Clone)]
struct Db(sqlx::PgPool);
#[carmy::tool(description = "Place an order", effect = "write")]
async fn create_order(State(db): State<Db>, input: NewOrder) -> AgentResult<Order> {
db.insert(input).await
}
#[tokio::main]
async fn main() -> carmy::Result {
let db = Db(sqlx::PgPool::connect("postgres://localhost/shop").await.expect("database"));
carmy::app().state(db).run().await
}
  • Resolvido na inicialização. Uma dependência ausente falha quando o app sobe, nunca em uma requisição:

    tool registration failed: MISSING_STATE: tool `create_order` requires State<shop::Db>; register it with .state(..)
  • Indexado por tipo. Registre um valor por tipo. Use newtypes (struct ReadDb(Pool)) quando precisar de dois valores do mesmo tipo.

  • Clonado a cada execução. Toda execução recebe um clone, então use tipos baratos de clonar: Arc<T>, pools de conexão e clientes HTTP.

  • Quantos quiser por tool. Uma tool pode receber vários parâmetros State<T>.

#[carmy::tool(effect = "external_write")]
async fn notify(
State(db): State<Db>,
State(mailer): State<Arc<Mailer>>,
input: Notification,
) -> AgentResult<()> { /* … */ Ok(()) }

O AgentContext carrega dados do framework sobre a execução: quem está chamando, quais permissões tem e o cancelamento. O State<T> carrega a sua aplicação: bancos de dados e clientes. O Carmy mantém os dois separados de propósito, para que o contexto nunca vire um service locator.

A alternativa explícita é implementar Tool em uma struct que guarda as próprias dependências.