Liquid
Conecte seu agente a qualquer API HTTP em tempo real - descobre e mapeia qualquer API REST uma vez, depois busca dados tipados de forma determinística.
Documentação
Liquid
Conecte seu agente de IA a qualquer coisa — sem precisar escrever ou manter conectores.
Aponte o Liquid para uma URL ou um banco de dados e ele descobre a interface para você:
identifica a estrutura, mapeia para os campos que você pediu e lida com autenticação,
paginação e normalização — registros tipados, sem código de cliente. Quando a fonte
muda, ele re-mapeia e continua funcionando. A mesma API enxuta — fetch · query ·
write · sense — alcança APIs web, bancos de dados, outros agentes (MCP/A2A), e-mail
e até sistemas de IoT e industriais (MQTT, Modbus, OPC UA, BACnet). Um LLM faz o
aprendizado na configuração (e em mudanças); o caminho dos dados em si não faz nenhuma chamada de modelo.
O que um agente pode alcançar através do Liquid
Uma API voltada para agentes (fetch · query · write · sense) sobre tudo que um
agente possa precisar tocar — o Liquid descobre como falar com isso para que o agente
não precise. São os sentidos e as mãos do agente: fetch/query sondam,
sense percebe um fluxo de eventos ao vivo, write age no mundo.
- APIs web e mensageria — REST/JSON, GraphQL, SOAP/WSDL, gRPC, WebSocket, streams SSE/NDJSON, MQTT (pub/sub IoT — assine para sentir, publique para agir)
- E-mail — IMAP/SMTP (qualquer provedor, senha de app ou OAuth2
XOAUTH2) e a API do Gmail (OAuth2): leia uma caixa de entrada,sensenovos e-mails conforme chegam e envie - Industrial / OT — Modbus (CLPs, sensores) e OPC UA (nós da Indústria 4.0, assinaturas nativas) para o chão de fábrica; BACnet para edifícios (HVAC/BMS) — leia, escreva e sinta
- Dispositivos Android — celulares, TV boxes, quiosques via ADB: sinta
logcat, leiashell, aja cominput/am - Outros agentes e ferramentas — qualquer servidor MCP, agentes A2A, manifestos de plugins do ChatGPT
- Bancos de dados — Postgres (+ pgvector), MySQL/MariaDB, SQLite, DuckDB, SQL Server, Neo4j (grafo), MongoDB (documentos), Redis (chave-valor)
- Pessoas, lugares e coisas — um humano, uma casa ou um carro como nó via
connectors: Telegram (perceba mensagens,sendrespostas), Home Assistant (perceba mudanças de estado de uma casa inteligente inteira, aja viacall_service— luzes, fechaduras, mídia) e Smartcar (perceba um veículo conectado em ~30 marcas — localização/bateria/combustível — e aja:lock/unlock, carregue)
Aponte para um endpoint https://…, um DSN postgres://… / mongodb://… / redis://…,
um alvo grpc://… ou outro servidor MCP — a descoberta identifica a
interface, aprende sua estrutura e entrega registros tipados ao seu agente. O mesmo
fetch/query/write funciona independentemente do que está por baixo. Sem conector
por serviço para escrever manualmente; a integração se mantém sozinha quando a fonte
muda.
# A web API it has never seen — no spec, no connector, no auth
adapter = await liquid.get_or_create(
"https://api.openbrewerydb.org/v1/breweries",
target_model={"name": "str", "city": "str", "country": "str"},
auto_approve=True,
)
breweries = await liquid.fetch(adapter) # typed records
# A database is just another interface — same API, and it writes too
db = await liquid.get_or_create("postgresql://reader@host/shop",
target_model={"id": "int", "email": "str"},
auto_approve=True)
orders = await liquid.fetch(db, "/public/orders")
await liquid.write(db, "/public/orders", op="insert",
values={"email": "a@b.com", "total_cents": 9900},
allow_write=True) # opt-in; mutates the store
Você não escreve nenhum conector nem schema: um LLM aprende a interface uma vez na configuração (bancos de dados se autoinspecionam e pulam até isso), e a integração se auto-repara quando a fonte muda. O runtime é transporte determinístico puro — custo previsível, comportamento reproduzível, nada para supervisionar.
Feito para as restrições que agentes reais enfrentam
Alcançar tudo é metade da história. A outra metade é que agentes pagam por cada token, se confundem com formatos inconsistentes e não conseguem interpretar textos de erro. O Liquid responde a cada um com um primitivo concreto — tudo incluído, tudo no PyPI.
Controle de orçamento de contexto
# Search / aggregate server-side instead of fetch-then-filter — 10-100x fewer tokens
orders = await liquid.search(adapter, "/orders",
where={"total_cents": {"$gt": 10000}, "status": "paid"}, limit=20)
stats = await liquid.aggregate(adapter, "/orders",
group_by="status", agg={"total_cents": "sum", "id": "count"})
hits = await liquid.text_search(adapter, "/tickets", "shipping delay") # BM25-lite
data = await liquid.fetch(adapter, "/orders", max_tokens=2000) # budget cap
data = await liquid.fetch(adapter, "/customers", verbosity="terse") # id + 1-2 fields
Normalização entre fontes
liquid = Liquid(..., normalize_output=True)
# Stripe {amount:1000,currency:"usd"} · PayPal {value:"10.00",currency_code:"USD"}
# → Money(amount_cents=1000, currency="USD", amount_decimal=Decimal("10.00"))
Carimbos de data/hora (Unix / ISO 8601 / RFC 2822) são convertidos para UTC datetime; envelopes de
paginação ({data:[…]} / {results:[…]} / cabeçalhos Link) são achatados; campos de ID
são normalizados entre id / _id / uuid / *_id.
Intenções canônicas — um modelo mental único entre serviços
await liquid.execute_intent(adapter, "charge_customer",
{"customer_id": "cus_xyz", "amount_cents": 9999, "currency": "USD"})
# Same intent on Stripe / Braintree / Square / Adyen — 71 canonical intents
Recuperação estruturada — agentes se auto-curam sem interpretar texto
try:
await liquid.fetch(adapter, "/orders")
except LiquidError as e:
if e.recovery and e.recovery.next_action:
await agent.call_tool(e.recovery.next_action.tool, e.recovery.next_action.args)
Todo erro carrega um Recovery com next_action: ToolCall, retry_safe e
retry_after_seconds. 401 → store_credentials. 404/410 → repair_adapter. 429
→ tente novamente após o atraso informado. E quando o schema da fonte muda, os adaptadores
se auto-curam (repair_adapter) — o agente continua funcionando.
Custo previsível — saiba antes de chamar
est = await liquid.estimate_fetch(adapter, "/orders")
# FetchEstimate(expected_items=250, expected_tokens=52_000, confidence="high", …)
if est.expected_tokens < my_budget:
data = await liquid.fetch(adapter, "/orders")
Ferramentas emitidas por to_tools() carregam um bloco metadata (cost_credits,
typical_latency_ms, cached, idempotent, side_effects, related_tools) para que
o agente possa raciocinar sobre qual ferramenta escolher — e ferramentas ambientais
(liquid_check_quota, liquid_list_adapters, …) permitem perguntar sobre o estado em vez
de memorizá-lo.
Impacto medido
Benchmarks determinísticos em tarefas realistas de agentes (cenários com 500 pedidos, 200
chamados, HTTP simulado) — reproduzíveis via python -m benchmarks.run:
| Tarefa | Métrica | Linha de base | Com Liquid | Delta |
|---|---|---|---|---|
| Encontrar 10 pedidos acima de $100 | tokens | 75.482 | 1.519 | −98% |
| Receita por status (agregado) | tokens | 75.482 | 115 | −100% |
| Buscar cliente (apenas id+email) | tokens | 424 | 12 | −97% |
| Recuperar de erro 401 | próxima_ação estruturada | não | sim | — |
| Encontrar o chamado de envio | tokens | 14.588 | 154 | −99% |
| Consistência Stripe↔PayPal | sobreposição de campos | 0,11 | 1,00 | +9× |
| Pular chamada desperdiçada via estimativa | tokens | 14.943 | 0 | −100% |
Limite de orçamento max_tokens=2000 | tokens | 14.943 | 1.999 | −87% |
Metodologia completa + detalhamento por tarefa: benchmarks/RESULTS.md.
Instalação
pip install liquid-api # core + bundled MCP server (the `liquid-mcp` command)
pip install 'liquid-api[discovery]' # + an LLM for discovering spec-less REST APIs & field mapping
Você precisa de um LLM extra? Interfaces autodescritivas — OpenAPI, GraphQL,
gRPC, MCP, A2A, WSDL — e todos os bancos de dados (introspecção) são descobertos sem
LLM, e todo o runtime (fetch/query/write/sense) nunca chama um
modelo. Você só precisa de um backend LLM para descobrir uma API REST que não tem
spec legível por máquina (heurística + LLM) e para mapear seus campos. [discovery]
puxa o LiteLLM, que alcança OpenAI / Gemini / Anthropic / local / 100+ provedores;
ou escolha um diretamente:
pip install 'liquid-api[gemini]' # Google Gemini (or [anthropic]; OpenAI/local work with no extra via base_url)
pip install 'liquid-api[grpc]' # gRPC transport (reflection)
pip install 'liquid-api[ws]' # WebSocket transport
pip install 'liquid-api[pg]' # Postgres / pgvector (asyncpg)
pip install 'liquid-api[mysql]' # MySQL / MariaDB (aiomysql); SQLite needs no extra
pip install 'liquid-api[neo4j]' # Neo4j graph (Bolt / Cypher)
pip install 'liquid-api[duckdb]' # DuckDB (embedded analytics)
pip install 'liquid-api[mssql]' # SQL Server (ODBC; needs a system ODBC driver)
pip install 'liquid-api[mongodb]' # MongoDB (collections as endpoints)
pip install 'liquid-api[redis]' # Redis (keyspace namespaces as endpoints)
pip install 'liquid-api[mqtt]' # MQTT (IoT pub/sub)
pip install 'liquid-api[modbus]' # Modbus (industrial registers)
pip install 'liquid-api[opcua]' # OPC UA (Industry-4.0 nodes + subscriptions)
pip install 'liquid-api[bacnet]' # BACnet (building automation; ADB needs the system `adb` binary)
# Framework integration (LangChain / OpenAI / Anthropic / MCP) is built in — no extra package.
O núcleo não tem dependências — a biblioteca de cada backend é um extra opcional, importada apenas quando usada.
Veja funcionando — ao vivo, sem pré-configuração
Aponte o Liquid para uma API que ele nunca viu (sem adaptador, sem spec OpenAPI, sem auth)
e receba registros tipados — você não escreve nenhum conector; descoberta + mapeamento é o
único lugar onde um modelo roda. Executável de ponta a ponta via
examples/live_quickstart.py:
Connecting to an API Liquid has never seen:
https://api.openbrewerydb.org/v1/breweries
discovery method : rest_heuristic
mapped fields : ['name', 'city', 'state', 'country']
LLM calls so far : 2 (discovery + mapping)
fetch() -> 50 typed records; first 3:
{'name': '(405) Brewing Co', 'city': 'Norman', 'state': 'Oklahoma', 'country': 'United States'}
{'name': '(512) Brewing Co', 'city': 'Austin', 'state': 'Texas', 'country': 'United States'}
{'name': '1 of Us Brewing Company', 'city': 'Mount Pleasant', 'state': 'Wisconsin', 'country': 'United States'}
LLM calls during fetch : 0
LLM calls on 2nd fetch : 0
Você não escreveu conector, schema ou cola de autenticação — o Liquid aprendeu a interface por você e vai reaprendê-la se ela mudar. Esse é o ponto: integrações que você não constrói nem supervisiona.
Execute como servidor MCP (código aberto, auto-hospedado)
Exponha o motor para qualquer cliente MCP (Claude Desktop, Cursor, Claude Code) — ele roda no seu próprio processo, sem nuvem, sem conta, sem aprisionamento:
Um clique no Cursor (o botão escreve o servidor no seu mcp.json; adicione seu
OPENAI_API_KEY nas configurações de MCP do Cursor depois). Ou configure manualmente:
pip install liquid-api
export OPENAI_API_KEY=sk-... # or GEMINI_API_KEY / ANTHROPIC_API_KEY,
# or OPENAI_BASE_URL=http://localhost:11434/v1 for local (Ollama/vLLM)
liquid-mcp # or: python -m liquid.mcp_server
Instalação zero com uvx (o pacote liquid-mcp
faz o comando funcionar pelo nome) — Claude Code:
claude mcp add liquid --scope user -e OPENAI_API_KEY=sk-... -- uvx liquid-mcp
Claude Desktop / qualquer cliente MCP:
{ "mcpServers": { "liquid": {
"command": "uvx",
"args": ["liquid-mcp"],
"env": { "OPENAI_API_KEY": "sk-..." }
} } }
(ou após pip install liquid-api, remova uvx e use "command": "liquid-mcp" diretamente.)
Um clique no Claude Desktop: instale o pacote .mcpb —
ele pede sua chave de modelo na instalação (armazenada no chaveiro do SO), sem JSON
para editar. Requer uv na máquina.
Ferramentas: liquid_connect (descubra + mapeie qualquer interface), liquid_fetch,
liquid_query (busca/agregação no servidor), liquid_estimate (pré-verificação de
custo/tamanho, sem chamada), liquid_list_adapters, liquid_discover. A superfície é
somente leitura por padrão; inicie o servidor com LIQUID_ALLOW_WRITES=1 para também
expor liquid_execute (insert/update/delete em banco). Adaptadores e credenciais
persistem em ~/.liquid. Suportado por qualquer LLM — OpenAI, Gemini, Anthropic, qualquer
endpoint compatível com OpenAI/local via base_url, 100+ provedores via LiteLLM,
ou sua própria função através de CallableBackend.
Início rápido — agente LangGraph
from liquid import Liquid, InMemoryCache, RateLimiter
from liquid._defaults import InMemoryVault, InMemoryAdapterRegistry, CollectorSink
from liquid_langchain import LiquidToolkit
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
liquid = Liquid(
llm=my_llm, vault=InMemoryVault(), sink=CollectorSink(),
registry=InMemoryAdapterRegistry(), cache=InMemoryCache(), rate_limiter=RateLimiter(),
normalize_output=True, # cross-source canonical shapes
include_meta=True, # _meta block on every response
)
adapter = await liquid.get_or_create(
"https://api.shopify.com",
target_model={"id": "str", "total_cents": "int", "customer_email": "str"},
credentials={"access_token": "shpat_..."},
auto_approve=True,
)
tools = LiquidToolkit(adapter, liquid).get_tools()
agent = create_react_agent(ChatOpenAI(model="gpt-4o-mini"), tools)
result = await agent.ainvoke(
{"messages": [("user", "Find 5 recent orders over $100 from VIP customers")]}
)
As ferramentas do agente vêm com descrições ricas (QUANDO usar, NÃO PARA o quê, formato de retorno, custo), recuperação estruturada em todo erro e busca no servidor para que ele nunca puxe 500 pedidos para encontrar 5.
Toda interface, uma API
A descoberta identifica o alvo e marca cada endpoint com um protocolo; um
driver de transporte plugável o executa — mas a API voltada para agentes (fetch, query,
write, mapeamento, recuperação, cache, limites de taxa) é idêntica em todos eles.
| Interface | Runtime | Escrita | Instalação |
|---|---|---|---|
| REST / HTTP+JSON | ✅ | ✅ ações (POST/PUT/PATCH/DELETE) | — |
| GraphQL | ✅ query + paginação Relay | ✅ mutações | — |
| SOAP / WSDL | ✅ XML da stdlib | — | — |
| gRPC | ✅ unário + server-streaming (reflexão) | — | liquid-api[grpc] |
| WebSocket | ✅ leituras em lote limitadas + assinatura + sense ao vivo | — | liquid-api[ws] |
| SSE / NDJSON (server-push HTTP) | ✅ leituras em lote limitadas + sense ao vivo | — | — |
| MCP (agente) | ✅ chamar ferramentas / ler recursos + notificação sense | ✅ chamadas de ferramenta | — |
| A2A (agente) | ✅ JSON-RPC message/send para habilidades do AgentCard | — | — |
| Postgres (+pgvector) | ✅ tabelas/views, filtros, paginação, busca vetorial | ✅ | liquid-api[pg] |
| MySQL / MariaDB | ✅ tabelas/views, filtros, paginação | ✅ | liquid-api[mysql] |
| SQLite | ✅ tabelas/views, filtros, paginação | ✅ | — (stdlib) |
| DuckDB | ✅ tabelas/views, filtros, paginação | ✅ | liquid-api[duckdb] |
| SQL Server | ✅ tabelas/views, paginação OFFSET/FETCH | ✅ | liquid-api[mssql] |
| Neo4j (grafo) | ✅ tipos de rótulos/relacionamentos, filtros de propriedade | ✅ CRUD de nós | liquid-api[neo4j] |
| MongoDB (documento) | ✅ coleções, filtros de campo, paginação | ✅ | liquid-api[mongodb] |
| Redis (chave-valor) | ✅ namespaces de keyspace, valores tipados, paginação SCAN | ✅ SET/HSET/DEL | liquid-api[redis] |
| MQTT (IoT pub/sub) | ✅ assinar → lote + sense ao vivo | ✅ publicar | liquid-api[mqtt] |
| Modbus (industrial) | ✅ leitura de registradores/coils + polling por delta sense | ✅ escrita de registradores/coils | liquid-api[modbus] |
| OPC UA (industrial) | ✅ leitura de nós + assinatura nativa sense | ✅ escrita de nós | liquid-api[opcua] |
| BACnet (edifícios) | ✅ leitura de propriedades de objetos + polling por delta sense | ✅ escrita de propriedades | liquid-api[bacnet] |
| ADB (Android) | ✅ leitura de shell + logcat sense | ✅ ações de shell (input/am) | — (adb do sistema) |
| E-mail — IMAP/SMTP | ✅ leitura de caixa por UID + sense de novos e-mails | ✅ envio (MIME) | — (stdlib) |
| E-mail — API Gmail | ✅ listar/obter + history sense | ✅ messages.send | — (OAuth2) |
Leitura e escrita. liquid.write(adapter, endpoint, op="insert", values={...}, allow_write=True) mutates any database (SQL INSERT/UPDATE/DELETE, insert/update/delete no Mongo,
Redis SET/HSET/DEL, CRUD de nós no Neo4j); escritas web/agente
passam por ações verificadas. Identificadores vêm da introspecção e
valores são parametrizados; update/delete exigem um where (sem
mutações genéricas); escritas ficam desligadas até você optar com allow_write=True.
Sense — o órgão aferente. liquid.sense(adapter, endpoint) percebe um fluxo de eventos ao vivo onde quer que exista: deltas de linhas SQL (e LISTEN/NOTIFY do Postgres), Redis pub/sub, frames WebSocket, server-push HTTP (SSE/NDJSON) e notificações MCP — cada um produzido como um evento agnóstico de modalidade. Apontado para dentro, liquid.sense_webhook(port=…, verifier=…) hospeda um endpoint de entrada para que um serviço (ou um humano, via webhook) que faça POST para o agente se torne também um sinal perceptível. Tudo limitado por max_events / max_seconds, para que um agente possa drenar por pull.
O loop sensorimotor. react(stream, handler) aciona um handler para cada evento percebido — com isolamento de erros e concorrência limitada — para que um host possa perceber → acordar o agente → agir. merge_senses(*streams) distribui vários sentidos em um único loop, para que um agente possa observar um banco de dados, uma fila e um webhook ao mesmo tempo:
events = merge_senses(
await liquid.sense(orders, "/orders"),
await liquid.sense_webhook(port=8088, verifier=stripe_verifier),
)
await react(events, on_event, max_concurrency=4)
A descoberta é automática — e identifica em tempo real. Antes do pipeline ser executado, uma etapa de fingerprint nomeia o alvo: um host:port simples é normalizado pela porta conhecida (db:5432 → postgresql://db:5432), e liquid.identify(url) responde "o que é isso, e o driver está instalado?" com uma dica de instalação quando um backend está ausente. (Identificar um protocolo é viável em tempo real; falar um novo protocolo binário autenticado não é — então desconhecidos são nomeados, não adivinhados.)
| Descoberta | Onde procura | Custo |
|---|---|---|
| Bancos de dados | introspecção de catálogo (postgres://, mysql://, mongodb://, redis://, neo4j://, …) | Baixo |
| gRPC / WebSocket / SSE | reflexão de servidor / amostragem de frames / detecção de content-type | Baixo |
| MCP / A2A / Plugin | /mcp, /.well-known/agent-card.json, /.well-known/ai-plugin.json | Baixo |
| OpenAPI / GraphQL / SOAP | spec, introspecção ou WSDL | Baixo |
| Heurística REST | caminhos comuns + interpretação por LLM | Médio |
| Navegador | Playwright capturando rede | Alto |
Adicione um backend sem escrever código. Para a família SQL, o contrato é declarativo o suficiente para ser dados: um manifesto de dialeto (aspas, estilo de placeholder, paginação, SQL de introspecção, mapa de erros, módulo DBAPI2) registrado via register_sql_manifest({...}) instala um driver funcional + descoberta — então um novo armazenamento SQL / compatível com wire (CockroachDB, ClickHouse, qualquer driver DBAPI2), até mesmo um obtido da rede como JSON, conecta-se sem um release. Novos protocolos, caso contrário, plugam via protocolo liquid.transport.ProtocolDriver; backends SQL compartilham um núcleo ciente de dialeto, então um novo é um adaptador de ~80 linhas.
Quer ensinar um novo protocolo ao Liquid? Um driver de transporte completo (fetch/write/sense) normalmente tem ~150 linhas — veja docs/ADDING_A_DRIVER.md para o passo a passo e uma lista de desejos (CAN bus, CoAP, KNX, AMQP, NATS, SNMP, …). Contribuições são bem-vindas.
Mais de 2.500 APIs são pré-descobertas e pré-mapeadas no catálogo global — a maioria dos serviços populares conecta-se com custo zero de descoberta.
Arquitetura
URL / DSN Agent
↓ ↑
FINGERPRINT → DISCOVERY FETCH · QUERY · WRITE · SEARCH · AGGREGATE
↓ ↑
one ProtocolDriver per Deterministic per-protocol transport
interface: • Query DSL (server-side filter)
REST GraphQL gRPC WS SSE MQTT • Output normalization
MCP A2A · SQL graph doc KV · • Verbosity / max_tokens / _meta
Modbus OPC-UA BACnet ADB … • (full protocol list in the table above)
↓ • Structured recovery + self-heal
APISchema • Rate-limit-aware token bucket
↓ • Response cache (Cache-Control aware)
AI MAPPING (setup only) • Empirical probing data (Cloud)
↓
AdapterConfig
A IA participa apenas na configuração. O runtime é puramente transporte com transformações — sem LLM por chamada, custo previsível, comportamento reproduzível (exceto search_nl, que armazena em cache suas compilações).
Componentes substituíveis
Cada preocupação transversal é um Protocol que você pode substituir:
from liquid.protocols import (
Vault, LLMBackend, DataSink, KnowledgeStore, AdapterRegistry, CacheStore,
)
Implementações em memória acompanham todos eles; liquid-cloud fornece PostgresVault, RedisCache, etc. para implantações hospedadas.
Suporte a frameworks
adapter.to_tools(format="anthropic") # Claude tool use
adapter.to_tools(format="openai") # OpenAI function calling (LangChain/CrewAI consume these)
adapter.to_tools(format="mcp") # MCP (Claude Desktop, Cursor)
Integração com frameworks
Nenhum pacote extra para instalar — está embutido no liquid-api. adapter.to_tools(format="anthropic" | "openai" | "mcp") emite definições de ferramentas prontas para uso para uso de ferramentas do Claude, chamada de funções da OpenAI (que LangChain / LangGraph e CrewAI consomem diretamente) e qualquer cliente MCP (Claude Desktop, Cursor, …). O servidor liquid-mcp incluído também expõe o Liquid como ferramentas MCP prontas para uso.
Comparação
| Recurso | Liquid | Zapier | Ferramenta LangChain | DIY |
|---|---|---|---|---|
| Descobre automaticamente qualquer interface (sem conector curado) | sim | não | não | não |
| APIs + bancos de dados + agentes em uma única camada | sim | parcial | não | não |
| Leitura e escrita através de uma única API | sim | sim | parcial | não |
| Busca / agregação no servidor | sim | não | não | parcial |
| Normalização de saída entre fontes | sim | parcial | não | não |
| Recuperação estruturada com next_action | sim | não | não | não |
| Autocorreção em desvio de esquema | sim | não | não | não |
| Estimativa de custo pré-execução | sim | não | não | não |
| MCP + A2A + LangChain + CrewAI nativo | sim | não | parcial | não |
| Código aberto | sim | não | sim | n/a |
Documentação
- Quickstart — descubra → mapeie → busque, além do runtime sem LLM
- OSS vs. Cloud — a fronteira honesta: gratuito/auto-hospedado vs. hospedado
- Arquitetura
- Estendendo — implemente seu próprio Vault / LLM / Sink
- Especificação de operações de escrita