Construa um agente
Esta página leva você do zero a um agente seu, respondendo sobre HTTP: uma conta, uma chave, uma
licença, duas ferramentas, um agent.yaml, um turno, uma confirmação e o stalwart serve.
Abra uma conta
Cadastre-se em stalwart.it, com o seu endereço de e-mail ou com o Google. Uma conta gratuita é aberta com a sua primeira chave de API, no console em api.stalwart.it/console. A chave é mostrada uma única vez, quando é criada: copie-a nesse momento. O que o plano gratuito inclui, e o que os planos pago e enterprise acrescentam, está em stalwart.it.
Instale o pacote e ative a licença
$ pip install "stalwart-agents[anthropic]" # or openai, google, mistral, ollama; or none, for no model at all
$ export QLS_API_KEY=qls_live_...
$ stalwart licence activate
stalwart licence activate é executado uma vez em cada máquina que executa os seus agentes. Nada
no pacote funciona sem a chave e uma licença ativada; o stalwart doctor diz o que falta e como
corrigir. A licença e o runtime diz o que é uma licença
e o que funciona sem ela.
Escreva as ferramentas
Uma ferramenta é uma função Python comum. As suas anotações de tipo são o seu esquema, a primeira
linha da sua docstring é o que ela faz, e @tool(...) lhe dá as palavras que as verificações leem:
# shop/tools.py
from decimal import Decimal
from stalwart_agents import tool
def get_order(order_id: str) -> dict:
"""Show an order: its items, its total and its status."""
return {"order_id": order_id, "total": "42.00", "status": "paid"}
@tool(writes=True, undo="refund_card")
def charge_card(order_id: str, amount: Decimal) -> dict:
"""Charge the card on file for an order."""
return {"charged": str(amount)}
@tool(writes=True)
def refund_card(order_id: str, amount: Decimal) -> dict:
"""Refund an amount to the card on file for an order."""
return {"refunded": str(amount)}
writes=True diz que a ferramenta altera algo, de modo que a sua chamada é verificada pelas suas
regras antes de ser executada. undo="refund_card" diz como a escrita é desfeita se a execução
falhar depois dela.
Declare o agente
# agent.yaml
agents:
desk:
model: "anthropic:claude-sonnet-5-5" # your provider and key, from your environment
tools: [get_order, charge_card, refund_card]
on_unread: model # a turn no tool covers goes to the model
tools:
- python: shop.tools # every public function of the module
runs: atomic # a failed run is undone, last write first
storage: sqlite:///runs.db # where runs and waiting confirmations are kept
O modelo só é chamado onde este arquivo envia um turno para ele: aqui, um turno que nenhuma
ferramenta cobre. Omita model, ou defina on_unread: refuse, e nenhum modelo é chamado
(exemplos completos).
Verifique-o antes de colocá-lo no ar
$ stalwart verify agent.yaml
O stalwart verify registra o catálogo, verifica cada caminho do grafo dos agentes e caça bugs no
rulebook, e sai com 1 quando o portão falha, de modo que funciona na CI como funciona aqui. O
catálogo que ele registra é aquele com que a planilha de regras abaixo é confrontada, e ele traz o
rulebook contra o qual o grafo foi provado, para que cada verificação de ferramenta o aplique
(protegido e provado).
Defina as regras
As regras sobre as suas ferramentas são uma planilha que uma pessoa pode ler em voz alta. Aqui, toda cobrança espera por uma pessoa, e nada acima de 200 é reembolsado sem a aprovação de um supervisor:
# rules.yaml
rules:
- action: charge_card
requires_confirmation: true
- action: refund_card
requires: [supervisor_approved]
when: { amount_over: 200 }
$ stalwart rules compile rules.yaml --save
--save registra a planilha no seu catálogo mais recente, e toda verificação de ferramenta a
aplica a partir de então. Uma regra que o compilador não consegue expressar com exatidão é recusada
com a sua linha, nunca aproximada.
Converse com ele
from stalwart_agents import Agent
desk = Agent.from_file("agent.yaml") # the graph is verified once, before the first turn
reply = desk.chat("show me order 4411", user="u-17")
print(reply.text) # get_order was chosen from the words; no model was asked
Confirme uma escrita
Uma escrita que, segundo as regras, precisa de uma pessoa espera por ela. A resposta diz o que espera, nas palavras que uma pessoa aprova:
reply = desk.chat("charge 42.00 to order 4411", user="u-17")
for waiting in reply.waiting:
print(waiting.tool, waiting.wording, waiting.decisions) # charge_card ... ['approve', 'skip', 'cancel_all']
reply = desk.confirm("u-17", "approve") # the call runs now, with the exact arguments shown
skip recusa esta chamada e segue adiante; cancel_all interrompe a execução e desfaz o que ela
escreveu.
Coloque-o no ar
$ export QLS_OPERATOR_TOKEN=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
$ stalwart serve agent.yaml
Abra http://127.0.0.1:8700/ para a interface de chat, com as suas confirmações, recusas e
reversões. As mesmas rotas respondem a qualquer cliente:
$ curl -X POST http://127.0.0.1:8700/threads/t-17/messages -d '{"text": "show me order 4411"}'
$ curl http://127.0.0.1:8700/threads/t-17/interrupts # what waits for a person
$ curl -X POST http://127.0.0.1:8700/threads/t-17/resume -d '{"interrupt_id": "...", "decision": "approve"}'
Um operador desfaz a execução de uma conversa com POST /threads/{id}/rollback, que exige o token
de operador como Authorization: Bearer; sem token definido (--operator-token ou
QLS_OPERATOR_TOKEN), a rota responde 403 e diz como definir um. Com storage: postgres://...,
vários workers respondem às mesmas conversas, e uma confirmação é retomada em qualquer worker que a
receba.
A seguir
- Exemplos completos: o modelo chamado só onde você permite, ou nunca; reversões controladas; uma planilha de regras; respostas a partir dos seus documentos; uma equipe de agentes verificada antes de rodar.
- A visão geral: cada parte do
agent.yamle cada comando. - A referência da API Python (em inglês):
Agent,toole o resto.