LangChain e LangGraph

stalwart_agents.langchain coloca o roteamento, a verificação de ferramentas e as sagas da Stalwart dentro de agentes LangChain e LangGraph. Nenhum seletor, vocabulário ou verificação está neste módulo. Toda decisão sobre a qual ele age é tomada pelo runtime que o wheel traz, na mesma máquina, sob a sua licença, ou pelo qls-router enterprise que você executa no seu próprio ambiente, onde o cliente o nomeia (router_url). A API hospedada da Stalwart não toma nenhuma delas. Um turno que precisa de um cálculo que nenhuma ferramenta responde é executado pelo nó de cálculo na imagem de contêiner qls-sandbox no seu próprio host, onde há um mecanismo de contêineres e a imagem; nos demais casos, ele é recusado, com um motivo que começa com compute off:.

$ pip install stalwart-agents                # the middlewares, the graph parts, Guard
$ pip install "stalwart-agents[otel]"        # OpenTelemetry spans
$ pip install "stalwart-agents[postgres]"    # resume confirmations from Postgres (or [sqlite])
$ pip install "stalwart-agents[nemo]"        # the NeMo Guardrails actions and rails

LangChain: dois middlewares, um importador, um callback

from langchain.agents import create_agent
from stalwart_agents.langchain import (StalwartRouterMiddleware, StalwartToolGuardMiddleware,
                                StalwartFeedbackCallback, register_catalogue)

register_catalogue(tools, agent="desk", client=client)            # POST /v1/catalogues
agent = create_agent(model, tools, middleware=[
    StalwartRouterMiddleware(client, agent="desk", on_unread="refuse"),
    StalwartToolGuardMiddleware(client, agent="desk"),
])

LangGraph: as partes, ou o grafo inteiro

from stalwart_agents.langchain.graph import create_stalwart_agent

agent = create_stalwart_agent(model, tools, catalogue=catalogue, agent="desk", client=client,
                              checkpointer=checkpointer)            # verified once per graph digest
Parte O que faz
StalwartState os nossos canais ao lado das suas mensagens: a sessão, o histórico (só de acréscimo), os rótulos de confiança, a saga, as confirmações em aberto, o plano
stalwart_messages, trim_pairs add_messages, e uma chamada de ferramenta nunca deixada sem o seu resultado; resultados na ordem das chamadas; um corte que mantém os pares
stalwart_route_node o turno lido em um plano, devolvido como Command com os seus destinos declarados
StalwartToolNode toda chamada verificada (congelar, verificar, executar uma vez, registrar, empilhar a reversão), um passo por vez, de modo que uma falha no meio de uma chamada é retomada com honestidade
stalwart_edge uma aresta condicional que só pode tomar os destinos que declara, e um rejected_route nos demais casos
stalwart_rollback_node, stalwart_rewind_node uma execução que falhou desfeita da última para a primeira escrita, passando pela verificação, e depois a memória rebobinada, nunca com uma reversão pendente e nunca o histórico
stalwart_hand_off_node uma transferência que leva o rótulo do agente que a faz
stalwart_branches, stalwart_join_node as chamadas de uma mensagem distribuídas como ramos Send, verificadas um histórico por vez e desfeitas na ordem inversa de conclusão; as reversões de um subgrafo entregues ao pai quando ele conclui, e a sua falha passa a ser do pai quando não conclui
with_stalwart_channels os nossos canais acrescentados a qualquer esquema de estado, para um supervisor, um swarm ou o seu próprio grafo que executa um agente stalwart ao longo dos turnos
create_stalwart_agent, build_stalwart_graph o grafo gerado a partir do seu catálogo, verificado pelo modo graph; compile() verifica todos os nós que você acrescentar
validate_state, validating cada quebra do estado nomeada, inclusive o token de encadeamento do histórico com history_verifier; o modo de depuração para no nó que a causou
export_graph, replay_witness a exportação que o verificador lê, e a testemunha de um achado reproduzida com toda ferramenta substituída por um stub

Python puro: Guard

from stalwart_agents.langchain.guard import Guard

guard = Guard(client, agent="desk", catalogue=catalogue, tools=[charge_card, refund_card])
with guard.run(guard.session()) as run:
    run.call(charge_card, order_id=o, amount=a)    # checked, keyed, its undo pushed
    run.call(provision_account, order_id=o)        # raises -> the charge refunded

stalwart_agents.langchain.guard não carrega nem LangChain nem LangGraph.

Em volta do agente