">
VICTOR SAAD
All buildsTodos os projetos
Open source (agent-team, MIT) · Claude Code · MCP · Python

Tell's agent teamO time de agentes do Tell

A small company's worth of roles, run by Claude Code agents. They hand work to each other through a shared mailbox, review each other's code and bring the humans only the decisions that are actually theirs.

Os papéis de uma pequena empresa, ocupados por agentes do Claude Code. Eles passam trabalho entre si por uma caixa de correio compartilhada, revisam o código um do outro e só levam às pessoas as decisões que são de fato delas.

Claude CodeMCP serverPython stdlibSQLiteThree.jssystemdv0.2
Code on GitHub: run the demo in two commandsCódigo no GitHub: rode a demonstração em dois comandos →
The office on Tell: each agent walks to its desk when it has work, envelopes fly between them as they message each other, and they go back to the kitchen when they're done. The screen is real; the conversation in this clip is a scripted replay, so nothing about customers or internal work is shown.O escritório no Tell: cada agente vai até a sua mesa quando tem trabalho, envelopes voam entre eles quando trocam mensagens, e eles voltam para a cozinha quando terminam. A tela é real; a conversa deste vídeo é uma reprodução encenada, então nada sobre clientes ou trabalho interno aparece.

Where it came from

De onde veio

Tell is built by two founders with day jobs, so I put a team of agents on it: tech lead, PM, two devs, QA, marketing, sales and social. After a few weeks of running it every day, the part worth sharing was not the prompts, it was the plumbing. agent-team is that plumbing, rewritten without anything from Tell, with a fictional example team you can run on your laptop.

O Tell é feito por dois sócios que têm emprego, então coloquei um time de agentes nele: tech lead, PM, dois devs, QA, marketing, vendas e social. Depois de algumas semanas rodando todo dia, o que valia compartilhar não eram os prompts, era o encanamento. O agent-team é esse encanamento, reescrito sem nada do Tell, com um time de exemplo fictício que roda no seu notebook.

Six days in production: what the numbers showed

Seis dias em produção: o que os números mostraram

Before opening the code I looked at what Tell's own team did between 16 and 21 October, from its mailbox and run log. Counts only, no message content.

Antes de abrir o código, olhei o que o próprio time do Tell fez entre 16 e 21 de outubro, a partir da caixa de correio e do registro de execuções. Só contagens, nenhum conteúdo de mensagem.

608agent runsexecuções de agentes
1,4531.453messages in the mailboxmensagens na caixa
39pull requests reviewed and merged by the QA agent (19–21/10)pull requests revisados e mergeados pelo agente de QA (19–21/10)
66%of all merged PRs in those days went through itde todos os PRs mergeados nesses dias passaram por ele

Humans see about one message in seven

As pessoas veem cerca de uma mensagem em cada sete

Between agentsEntre agentesTo the foundersPara os sócios
Messages per day: between agents and to humans010020030040016/10: 53 to humans / para pessoas16/10: 352 between agents / entre agentes40516/1017/10: 21 to humans / para pessoas17/10: 192 between agents / entre agentes21317/1018/10: 2 to humans / para pessoas18/10: 40 between agents / entre agentes4218/1019/10: 33 to humans / para pessoas19/10: 232 between agents / entre agentes26519/1020/10: 47 to humans / para pessoas20/10: 273 between agents / entre agentes32020/1021/10: 40 to humans / para pessoas21/10: 168 between agents / entre agentes20821/10
Messages per day. 196 of 1,453 (13%) went to a founder; the rest stayed between agents. 18/10 was a Saturday with the team mostly paused.Mensagens por dia. 196 de 1.453 (13%) foram para um sócio; o resto ficou entre os agentes. 18/10 foi um sábado com o time quase todo pausado.
Show the numbersVer os números
TotalTo humansPara pessoas
16/1040553
17/1021321
18/10422
19/1026533
20/1032047
21/1020840

Review and coordination were half the bill

Revisão e coordenação eram metade da conta

Share of cost by roleQAQA: 28.4% · 200 runs28.4%Tech LeadTech Lead: 24.6% · 155 runs24.6%CMOCMO: 15.0% · 79 runs15.0%Dev BackDev Back: 14.7% · 75 runs14.7%Dev FrontDev Front: 11.3% · 40 runs11.3%SellerSeller: 2.9% · 46 runs2.9%PMPM: 2.3% · 10 runs2.3%SocialSocial: 0.5% · 3 runs0.5%
Share of cost by role. QA and the tech lead took 53%: every pull request went through several review rounds, and the lead woke up every hour whether or not there was anything to move.Parcela do custo por papel. QA e tech lead ficaram com 53%: cada pull request passava por várias rodadas de revisão, e o lead acordava toda hora, tendo ou não algo para mover.
Show the numbersVer os números
%RunsExecuções
QA28.4200
Tech Lead24.6155
CMO15.079
Dev Back14.775
Dev Front11.340
Seller2.946
PM2.310
Social0.53

And the founders were approving all day

E os sócios passavam o dia aprovando

Approval requests to the founders per day0102016/10: 131316/1017/10: 111117/1018/10: 1118/1019/10: 121219/1020/10: 232320/1021/10: 222221/10
Approval requests per day, up to 23. Worse, an "approved" in a thread went to whoever spoke last, sometimes the wrong agent.Pedidos de aprovação por dia, até 23. Pior: um "aprovo" numa thread ia para quem falou por último, às vezes o agente errado.
Show the numbersVer os números
Approval requestsPedidos de aprovação
16/1013
17/1011
18/101
19/1012
20/1023
21/1022

What changed: an orchestrator

O que mudou: um orquestrador

The fix was not a better prompt, it was structure. Version 0.2 adds an optional orchestrator, ported from what now runs on Tell:

A solução não foi um prompt melhor, foi estrutura. A versão 0.2 traz um orquestrador opcional, portado do que hoje roda no Tell:

  • One door. A message without an addressee goes to the orchestrator, even inside a thread, so "approved" never lands on the wrong agent.
  • Authority levels. What the team does alone, what it logs, what needs one question with a recommendation, and what needs a human now.
  • Approvals with a receipt. Every request becomes a tracked decision. An ambiguous "approved" covering a pull request and e-mails approves no e-mail; the orchestrator asks, then confirms what it understood.
  • A merge gate in code. The reviewer only gives a verdict. The dispatcher merges when CI is green on that commit, no decision is pending and, for sensitive paths, a human said yes. One review round instead of many.
  • Promises. "I'll let you know when..." has to be a registered promise; the dispatcher wakes the agent when it is due and flags it when late.
  • A daily digest built by code. Non-urgent news waits for one message a day instead of trickling in.
  • Heartbeat by trigger and a weekly retro that reads the numbers and proposes at most a few changes, each waiting for approval.
  • Porta única. Mensagem sem destinatário vai para o orquestrador, mesmo dentro de uma thread, então um "aprovo" nunca cai no agente errado.
  • Níveis de alçada. O que o time faz sozinho, o que só registra, o que pede uma pergunta com recomendação e o que precisa de uma pessoa agora.
  • Aprovação com recibo. Todo pedido vira uma decisão rastreada. Um "aprovo" ambíguo, que cobre um pull request e e-mails, não aprova nenhum e-mail; o orquestrador pergunta e depois confirma o que entendeu.
  • Portão de merge em código. O revisor só dá o veredito. O dispatcher faz o merge quando o CI está verde naquele commit, não há decisão pendente e, em caminhos sensíveis, uma pessoa disse sim. Uma rodada de revisão em vez de várias.
  • Promessas. "Te aviso quando..." precisa virar uma promessa registrada; o dispatcher acorda o agente no prazo e avisa quando atrasa.
  • Resumo diário montado por código. Novidade que não é urgente espera uma mensagem por dia, em vez de pingar o dia todo.
  • Heartbeat por gatilho e uma retro semanal que lê os números e propõe no máximo algumas mudanças, cada uma esperando aprovação.

It went live on Tell on 21 October; it is too early for a before-and-after, and I will add one here when there is a full week to compare.

Entrou no ar no Tell em 21 de outubro; ainda é cedo para um antes e depois, e vou colocar aqui quando houver uma semana inteira para comparar.

How it works

Como funciona

  • Roles are configuration. One team.json lists the agents, their prompts and allowed tools, the humans, who approves what, routines and triggers.
  • A mailbox exposed as an MCP server. Agents use ask, assign, reply, share, request_approval and remember. SQLite, Python standard library only.
  • A dispatcher that wakes an agent only when it has mail. Nobody polls, each run takes minutes, messages from a human go first, and there are caps per day and per run.
  • Routines and triggers. "Monday 10:00, marketing drafts the newsletter"; "a new line in this error log becomes a task".
  • Optional integrations, off by default: Discord (one thread per conversation), e-mail over SMTP, a GitHub pull request queue.
  • Papéis são configuração. Um team.json lista os agentes, seus prompts e ferramentas permitidas, as pessoas, quem aprova o quê, rotinas e gatilhos.
  • Uma caixa de correio exposta como servidor MCP. Os agentes usam ask, assign, reply, share, request_approval e remember. SQLite, só biblioteca padrão do Python.
  • Um dispatcher que só acorda o agente quando ele tem mensagem. Ninguém faz polling, cada execução leva minutos, mensagem de pessoa passa na frente, e há limite por dia e por execução.
  • Rotinas e gatilhos. "Segunda 10h, marketing rascunha a newsletter"; "linha nova neste log de erro vira tarefa".
  • Integrações opcionais, desligadas por padrão: Discord (uma thread por conversa), e-mail por SMTP, fila de pull requests no GitHub.

The office

O escritório

Logs are honest but nobody reads them. The office is a 3D floor plan in the browser: agents walk to their desks when they have work, envelopes fly between them, and a panel shows the day's runs, messages, tokens and what they would cost at API prices. A replay mode plays a scripted conversation; the repository ships one, pictured below.

Log é honesto, mas ninguém lê. O escritório é uma planta 3D no navegador: os agentes vão até a mesa quando têm trabalho, envelopes voam entre eles, e um painel mostra as execuções, mensagens e tokens do dia e quanto custariam a preço de API. O modo replay reproduz uma conversa roteirizada; o repositório traz uma, na imagem abaixo.

The agent-team office: a 3D floor plan with the lead, dev, reviewer, marketing and support agents, a conversation feed and a control panel
The office playing the scripted demo that ships with the code: a made-up online tea shop with an ops orchestrator, a lead, a dev, a reviewer, marketing and support, and two owners who only approve.O escritório rodando a demonstração roteirizada que vem com o código: uma loja online de chá inventada, com um orquestrador (Ops), lead, dev, revisor, marketing e atendimento, e dois donos que só aprovam.

Security first, limits stated

Segurança primeiro, limites declarados

Agents read untrusted text, so the framework assumes any of them can be talked into anything its tools allow. The answer is least privilege, not detection:

Agentes leem texto não confiável, então o framework parte do princípio de que qualquer um deles pode ser convencido a fazer tudo o que as ferramentas permitem. A resposta é privilégio mínimo, não detecção:

  • Per-role tool lists and normal permission mode by default; full bypass only inside a sandbox.
  • Outgoing e-mail is enforced, not just requested: a separate mailer sends only what a human approved, checked with an HMAC, and only if the text is unchanged.
  • Secrets stay with the services that need them, never in prompts or messages; attachments are checked for keys and env files.
  • Budgets and a stop button: few runs at once, daily caps, a timeout per run, agent-team stop.
  • Lista de ferramentas por papel e modo de permissão normal por padrão; bypass total só dentro de sandbox.
  • O e-mail que sai é garantido, não só pedido: um mailer separado só envia o que uma pessoa aprovou, conferido por HMAC, e só se o texto não mudou.
  • Segredos ficam com os serviços que precisam deles, nunca em prompts ou mensagens; anexos são conferidos contra chaves e arquivos de ambiente.
  • Limites e botão de parar: poucas execuções ao mesmo tempo, teto diário, timeout por execução, agent-team stop.

The README says plainly what it doesn't do: it runs on one machine, prompt injection is not solved, and only e-mail and the merge gate are enforced in code. The gate can't stop an agent that holds a merge token from merging by hand, so the docs say to keep that token away from the agents.

O README diz com clareza o que ele não faz: roda numa máquina só, prompt injection não está resolvido e só o e-mail e o portão de merge são garantidos em código. O portão não impede um agente que tenha token de merge de mergear na mão, então a documentação manda manter esse token longe dos agentes.

Try it

Experimente

git clone https://github.com/victoorsaad/agent-team && cd agent-team
python3 -m agent_team office --replay examples/tea-shop/replay.json
# http://127.0.0.1:8130

No Claude calls and no network needed for the demo. A dry-run mode then exercises the whole loop with a stub in place of Claude.

A demonstração não chama o Claude nem precisa de rede. Depois, um modo seco roda o ciclo inteiro com um stub no lugar do Claude.

Not Tell's code: Tell's own team, prompts and data stay private. Everything in the repository, including the tea shop, is fictional.
Não é o código do Tell: o time, os prompts e os dados do Tell continuam privados. Tudo no repositório, inclusive a loja de chá, é fictício.

Want to talk about this? I'm happy to walk through how it was built.Quer conversar sobre isso? Mostro com prazer como foi construído.