🇧🇷 Português · 🇺🇸 English

mead

CI Lint Coverage: 93%+ License: MIT Elixir 1.20+ Hex.pm

Runtime para assistentes baseados em LLM sobre Elixir/OTP: sessões supervisionadas, um router de modelos local/nuvem e cliente e servidor MCP.

Início rápido

Requer Elixir 1.20+ sobre Erlang/OTP 29. Adicione o mead às dependências no mix.exs:

def deps do
  [{:mead, "~> 0.1"}]
end

Para trabalhar no próprio mead, veja o CONTRIBUTING.md.

O handler de turno padrão repete o texto, então uma sessão roda sem chave de API (iex -S mix):

{:ok, session_id} = Mead.start_session()
Mead.submit_turn(session_id, "hello")
#=> {:ok, "hello"}

Para rotear para modelos de verdade, configure os slots do router:

config :mead, :turn_handler, Mead.Router

config :mead, :router,
  slots: [
    local: {Mead.Provider.Ollama, model: "llama3.1"},
    cloud: {Mead.Provider.Anthropic, model: "claude-sonnet-5-5"}
  ]

Persistência, hub e servidor MCP e o endpoint do deck são ligados cada um por sua chave config :mead. O docs/ARCHITECTURE.md (em inglês) lista todas as opções.

Visão geral

Fluxo de um turno: o prompt de um cliente chega a uma sessão supervisionada, o router o envia a um modelo local ou de nuvem, e as chamadas de ferramenta passam pelo hub MCP, que nega por padrão. O log de eventos é gravado antes do envio e o ledger conta cada turno.
  • Sessões. Um grupo de processos supervisionado por conversa; a falha de um turno fica nessa conversa.
  • Router. Uma função sem estado que classifica cada turno como local ou nuvem. route: :local ou route: :cloud sobrescreve.
  • MCP. Um hub cliente para os servidores que você configurar e um servidor que expõe sessões como nove ferramentas.
  • Ledger. Tokens, chamadas de ferramenta e latência por sessão e por rota, com journal em disco.

Garantias

  • Um turno local nunca vai para a nuvem; um slot local vazio devolve :local_unavailable.
  • Ferramentas MCP são negadas a menos que a política permita; no deck, ferramentas :effect perguntam à pessoa antes.
  • O servidor MCP e o endpoint do deck não sobem sem um bearer token.
  • Nada é persistido nem cortado a menos que você configure storage e max_turns.

Notas de projeto

DecisãoPreço
Eventos do deck são gravados no log antes de serem enviadosUma escrita sincronizada por evento; o cliente que reconecta recebe exatamente o que perdeu.
O relógio do turno para enquanto um pedido de permissão esperaUma resposta lenta não derruba o turno; a espera tem limite próprio, permission_timeout_ms.
O ledger atualiza o ETS no processo que emitiu o eventoUm turno morto por timeout não emite evento e não é contado.
O histórico nunca é cortado por padrãoO arquivo da conversa cresce até você definir max_turns.

Projetos relacionados

agent-swarm-deck é o cliente Flutter que fala com o mead pelo WebSocket do deck, e open-butler guarda a lógica de domínio do assistente. Nenhum dos dois é necessário para rodar o mead.

Contribuir e segurança

Veja o CONTRIBUTING.md e o SECURITY.md para reportar uma vulnerabilidade em privado.

Licença

MIT © Alberto Cavalcanti


Feito por Alberto Cavalcanti · Conecte no LinkedIn · Docs · Arquitetura