SEIF Suite: one workspace, the context first
The web Workstation grew screen by screen: Agent Workspace, Context engineering, Lab, World, Studio, Data & go live and Team. Each of them is sound, but a project opened as seven overlapping workspaces, each with its own progress model and vocabulary. This document records why that failed people and how the suite replaces it.
Lay authoring, cross-topic links and a cold-AI benchmark (2026-11-04)
A product-engineering round on the Prova and Recebe tabs for a non-technical owner, with the engine changes that back them. Newest first:
- Prova is a verdict router, not a list. Pasting a real conversation still turns each customer question into a verdict (
agent-native.mjs → learn), but the vocabulary is now five — covered / sealed / out of date (stale) / not received (missed) / gap — and each verdict carries one routed next step: teach the answer, give it to the agent (the answer exists but the profile withholds it — fix the profile), renew the date, mark out of scope, or keep as a test. Proving runs against one or more agents at once (profiles[]): a COVERED question becomes a positive test (must: <locator>), a SEALED one — kept out of that agent's profile on purpose — a negative test (forbid: <locator>). A plain what your agent knows panel (built from the resolved world) shows the owner what each agent has in hand, within reach and sealed, without reading a profile file. - Learned tests are guarantees by default. A test written from a conversation is now
required: true(a release that loses it is blocked) unless the owner picks watch only, a namedrequired: falsedowngrade — the old default was the reverse. Its body is one clean sentence, its provenance the frontmatter fieldsource: learned from a conversation, and it is named after the agent it proves, not the raw profile id. - A misspelling is a one-click synonym, not a dead end.
learn,findand the Compass share one spelling rescue (didYouMeaninagent-native.mjs, Damerau–Levenshtein over the project's own vocabulary): a GAP caused by a typo offers the nearest real term, and Prova turns it into a project synonym (seif.yaml → search.synonyms). - Cross-topic references a lay user can make. A knowledge section can point at another (frontmatter
references:or a<!-- seif: references=a,b -->marker); when it is in hand, the agent gets a door to the linked section (resolve.mjs, reasonREFERENCED, honouring the profile seal and the frontier cap). The Ensinar modal links sections from a picker of existing sections (title + topic, never a raw locator); a dangling link is refused at authoring (UNKNOWN_REFERENCE), the same picker edits the links on an existing section, and a link that breaks later is reported byseif doctorasDANGLING_REFERENCE. See Retrieval and agent-native. - Out of scope silences the alert, reversibly. Marking a question out of scope records a
DELIBERATELY_UNCOVEREDdisposition; the Gaps board andnotifyGapsnow exclude it (gaps.mjs → gapBoard), so the decision is "out of scope" rather than a nagging "unanswered". A decisions view still lists it, and removing the disposition in advanced settings brings it back. - A cold-AI benchmark on the deploy surface. Agentes → Build e implantação gains a Benchmark sub-tab (
web/public/context.js,runtime/engine/benchmark.mjs). The plan is free and model-free — it counts the questions (from gaps and recent real turns) and estimates the cost. The run is gated behind a configured model key, asks for confirmation because it costs money, never rehearses silently, and records observable facts only per question, grouped by layer — it does not grade the answer with a model. - Conversation formats are presets the owner edits. Plain-text conversation parsing moved into
runtime/engine/conversation-format.mjs(CONVERSATION_FORMATS,compileFormat): small{time}/{name}/{message}templates (WhatsApp and the like) the owner can pick or edit, with continuation lines appended to the prior speaker.conversationSpeakers()lists who it found so the owner marks the business's own side instead of guessing. - Preview before write, everywhere a write happens. The teach and keep-as-test flows show the canonical destination — the knowledge file and section locator (
file.md#chunk), and the Context Test that will be written — before writing anything, ratified as the product invariantINV-PREVIEW-BEFORE-WRITE.
One canonical write, rigid agents by default, and a diagnostic mode (2026-11-03)
A dogfooding run — the owner using SEIF to build SEIF itself, connecting Cursor to a project's context server — surfaced a round of fixes to the Contexto experience and to how agents behave by default. Newest work, grouped:
- One canonical write, and the end of "the project changed in another window". Every guarded write from the browser (add/edit/toggle knowledge, create an agent, save behaviour, add a capability, publish a release) now goes through a single helper,
seif.commit(web/public/kit.js), which reads the fresh revision and retries once on a benign stale-revision refusal (PROJECT_CHANGED). A shared Context Profile that fans a change out to other agents goes throughseif.sharedChange, which confirms first. The per-call-site revision handling that caused the error is gone;drop.js(folder import) uses the same helper. - Adding knowledge always chooses the subject. The guessing is gone: the main O que o agente recebe screen no longer shows a suggestions panel built from a keyword matcher (it turned a paper's sections into "questions" and guessed pricing from the word "paper"). Instead, importing a folder opens a post-import step with the tour, example questions and knowledge topics, where they have a moment and a purpose. Every add-knowledge flow (teach a gap, import review, inline add) uses one subject chooser (
seif.ui.topicField): existing subjects appear as one-click chips, and a subject is pre-filled only on a strong match to an existing area, never asserted. The "include this file" checkbox appears only when there are two or more files, and dims the row when unchecked. One backend path:addKnowledgetakes an optionaltopic, so Studio and the desktop keep working. - A clear button, and the header that watches. O que o agente recebe has a Nova pergunta button that clears the result. The suite header carries two live indicators (server status and open gaps), polled every 20s (
suite.js → startStatusPoll), and a redeploy shortcut that publishes the current draft as a release Build so production takes the edits live. The agent selector (hidden when a project has one profile) is clearer about which agent a Compass answer is for. - Interactions record the whole connection. The context server logs not only tool calls but the session events — the handshake,
tools/listandping— so the owner can say with certainty that an agent connected and listed the tools but called nothing. A new Conexões section shows them. Caller identity is who holds the token (the link token is one "Token do projeto" group, agent tokens group by their id), fixing a bug that split one caller into duplicate groups. - Rigid agents by default, in the project's language (Etapa A). The MCP server's instructions (
runtime/engine/mcp.mjs → instructionsFor(mode, lang)) are now bilingual (EN_INSTRUCTIONS/PT_INSTRUCTIONS) and chosen by the project's language (web/host.mjspassesprojectLanguage(root)), and they are stricter: consult in silence, answer naturally, never expose the mechanism (tools, file names, locators, "I reported a gap"); when the answer is not there, use the situation's fallback message if one is set, otherwise be honest, say you will find out, and call the newcontext_report_gaptool so the owner sees it on the Gaps board. A new project's default agent (seif init, objective answer) is born with this behaviour, written in the chosen language (agent-native-text.mjs → agentDefaults(lang)): a Portuguese project no longer gets English instructions. The advanced owner edits freely. - Messages for when the agent cannot answer (Etapa A3). A profile may carry a
fallbackResponsewith up to three messages — gap, stale, blocked — set in Agentes → Comportamento → Quando não consegue responder and honoured by the resolver (resolve.mjs). Left blank, the agent stays honest and reports the gap (per the rigid default). The panel respects the interface language. - Diagnostic mode: a view for the owner, never for a customer, never in production (Etapa B). O que o agente recebe has a Modo diagnóstico toggle (
web/public/context-home.js), entirely client-side. On, it expands what the Compass already returns — per-section locators and match scores, raw frontier reason codes, the equivalent CLI command, and a block with profile, basis, verdict and the residual signal. When the agent names a reference teammate (agentCapabilities.reference), it runs the same question as that teammate and shows, side by side, what each would have in hand — so the owner sees what a hand-off would reach (Fase 3). A SEIF documentation panel signals the web docs (seifprotocol.com/docs) and searches SEIF's wholedocs/tree inline (migrationDocsSearch, which degrades to a lexical search offline). The guardrail: nothing here is a flag in the engine, the MCP server or the served Compass shape — the receive tab always runs on the draft, so the toggle cannot change what a customer or a production agent receives.
Any language, by words and by meaning (2026-10-30)
- Words in any script. One analyzer (
runtime/engine/text-analysis.mjs) for relevance, the Compass,learnandfind: ICU word segmentation (Japanese, Chinese, Thai…), Chinese/Japanese/Korean bigrams, stop words of twelve languages, a language-neutral 5-letter prefix stem, built-in synonym groups in six languages, and the project's own synonyms and ignored words (seif.yaml → search). The Portuguese-only stemmer and the Compass's PT/EN lists are gone. - Meaning, with SEIF owning the index.
search.semantic(any OpenAI-compatible embeddings endpoint) makesretrieverules hybrid: vectors per (endpoint, model, content digest), pinned in the Build (embeddings.json, verified, carried in Registry artifacts); the runtime embeds only the question. The Compass andlearnfind answers by meaning too. This closes the "indexing contract" gap of theexternalstrategy. - Conexões → Busca: how SEIF reads a question (words used, ignored, synonyms), what it finds by words and by meaning, the vocabulary, and the embeddings service with a connection test that reports cross-language similarity.
One kind of project, one example (2026-10-30)
- One kind of project. Novo projeto asks for a name and creates a project of files (
seif init). Its Agent Workspace, Lab, context map, versions, Build & deploy (the former Context engineering's Build/Deploy/Observe, now Agentes → Build e implantação), connections, going live and the Sales Kit are all configured inside it. The Agent Workspace (JSON), Context engineering (JSON) and reference-example kinds are gone;POST /api/projectsacceptskind: files(andteam, the same project with the team already on). A project imported in the earlier JSON format becomes files on import; there is no conversion back. The JSON-onlyPUT layer-rule/<layer>was unused and is removed. - One example. Clínica Aurora / Aurora Clinic is the only template (web, desktop and
seif init --template exemplo|example). Orientação and Vendas were removed; what they taught that was worth keeping now lives in the example: a sample WhatsApp conversation for Prova → Usar a conversa de exemplo (2 covered, 1 out of date, 1 gap) and theAGENTS.mdguidance for coding agents (now including SEALED). The agent starters (customer support, tutor, game character…) and the "example agents" of the Agent Lab are no longer offered: Novo agente starts blank. - One lexical ranking. Relevance is BM25 over accent-folded, stemmed terms with English and Portuguese stop words; the earlier TF·IDF and the
versionswitch are gone. - Fixed on the way. Equipe in a project without a team said "this project has no agents" and offered no way to turn the team on (its form had been removed;
template: blankrefused an existing folder): it now turns the team on in place. "Mark as reviewed today" renewedupdated:even when the area's rule judges another field (verificado:), so the file stayed out of date while the screen said it was reviewed: it now renews the field the rule judges.
A first session that shows the value (2026-10-30)
A new account met an empty project: asking a question there showed nothing (the empty state never rendered the verdict), the examples led to a 3D world, an English Lab or the legacy Context engineering, and templates opened in the Lab. Now:
- Open a ready example (welcome screen, Exemplos in the wizard, and the empty project's knowledge panel) creates Clínica Aurora / Aurora Clinic (
runtime/engine/templates.mjs→exemplo/example): fictitious data, two agents (Atendimento, Equipe), five passing tests and one intended stale price. Itsseif.yamllists four guided questions (examples:), shown under Experimente with what each proves: Ready, Out of date, Sealed by rule (switch to Equipe and it is Ready) and Nobody wrote this (teach it in one step). - Asking in an empty project shows the verdict (a gap) and Ensinar a resposta writes the first section and its test.
- Every project opens on Contexto.
- The Compass has a SEALED verdict: the answer exists and this agent's profile keeps it out on purpose. The owner sees sealed material (internal layers included) with its reason; the hosted MCP endpoint never names it.
- Fixed: "checado em [object Object]" on every dated section; English engine reasons and health findings in the Portuguese UI; English starter names in the Portuguese wizard; the landing promise ("Saiba o que seu agente sabe. Antes que ele responda.").
Contexto first, operations as a kit (2026-10-29)
A code-level comparison with Trinity (abilityai/trinity: a self-hosted OS that runs fleets of Claude Code, Codex and Gemini agents, with approvals, audit and channels) settled what the product is. Trinity's own agent guide says it plainly: "Agents manage their own memory. Trinity provides storage, not strategy." Running and orchestrating agents is a crowded layer; deciding what an agent knows, proving it and delivering it into whichever agent runs is not.
So a project now opens on Contexto, three screens over the engine with no model calls:
| Section | Route | What it does |
|---|---|---|
| O que o agente recebe | contexto/recebe | Ask as a customer would; see what the chosen agent has in hand (locator, layer, tokens, excerpt), what stays out and why (a door it opens by itself — including a cross-topic REFERENCED link — outside its profile, out of date), what is unknown and the one next step. A gap is taught in one step (knowledge + rule + check), and the teach form links to related sections from a picker (never a raw locator). |
| Prova | contexto/prova | The repository's health (seif doctor), the tests, and real conversations pasted from WhatsApp or e-mail. Each question gets a verdict — covered / sealed / out of date / not received / gap — and a routed next step: teach the answer, give it to the agent (fix the profile), renew the date, mark out of scope (silences the alert, reversibly) or keep as a test. Proves against one or more agents at once (positive must / negative forbid), suggests a synonym for a misspelling (did you mean), and shows a plain what your agent knows panel. Kept as a test in one click. |
| Conectar a um agente | contexto/conectar | The project's MCP server answering as one agent's profile, with recipes for Claude Code, Codex, Cursor, Claude.ai/ChatGPT, n8n/Zapier, Trinity (a ready agent ZIP) and OpenBot, and a connection test. |
A health strip (status, tests passing, coverage, sections, agents) tops every section. The rail lists Contexto, Agentes, Conexões; Hoje, Equipe, Rotinas, Atendimento and Pessoas are the Kit Vendas WhatsApp, an optional operational application installed deliberately from the rail. It runs its own embedded operational runtime for WhatsApp/Evolution, approvals and the sales funnel, while the SEIF Core remains Contexto. Every project of files starts on Contexto; Hoje remains an intentional destination for pending decisions and sales work.
The hosted context server
<handle>/<slug>/mcp (web/host.mjs) serves, besides the connected-API tools, the engine's context tools (runtime/engine/mcp.mjs → HOSTED_TOOLS: compass, find, resolve, why, test, doctor), bound to the profile the owner chose (mcp_links.context_profile). The caller cannot pick another profile, context_find searches only what that profile receives (selected, or a door it opens), and context_learn stays local because it reads files by path. Links made before this existed keep the context off until the owner turns it on. Production (…/mcp) answers from a release Build and staging (…/staging/mcp) from the draft; see SEIF and Trinity → Environments. A profile of an external agent is never offered the connected-API tools.
What was wrong (audit of app.seifprotocol.com, 2026-10-24, project "Missão CNH · team")
| # | Problem | Where |
|---|---|---|
| 1 | The hub asked people to choose an internal architecture before starting: Agente, Agente em arquivos, Equipe de IA, Context engineering, Exemplos. | Hub → Comece algo novo |
| 2 | Seven modes per project (agents, context, studio, lab, world, connect, team) with five different progress models: Team's 1–3, Data & go live's 1–5, the agent's 01–09, Context engineering's 01–05, World's 0/6 quests. | Every project |
| 3 | Menu labels did not match screen names: Run history opened "Living Studio", Context map opened "Context World", Files & rules opened "Lab", Context controls opened "Context engineering". | Top bar → Advanced |
| 4 | The same job lived in several places: Try it in four, tests in four (agent Tests, Context Tests, Lab Tests, World "Prove it"), data in two. | Agents, Lab, World, Go live |
| 5 | Contradictory status: the hub said Escritório aberto · Serviço de agentes ativo while Team said Setup needed, Go live said ✓ Choose a brain and the agent said subscription-cli · not checked. | Hub, Team, Go live, Agents |
| 6 | The work the owner actually does every day (the funnel, replies, approvals, the WhatsApp line, the partner API) was tab 2 of 6 inside Team, under a setup banner, with Your decisions below the board. | Team → Funil |
| 7 | Mixed languages on one screen: hub in Portuguese, project chrome in English, funnel and content in Portuguese. | Everywhere |
| 8 | XP, levels, streaks and quests competed with real work on the first screens. | Hub, World |
| 9 | Revenue Operations had no presence in the web product; its pipeline, approvals and sending were partly re-implemented as the Team funnel. | — |
The practical result, in the owner's words: running an agent client on the repository was easier than using the product.
The model
A project is a workspace for one business or initiative. Inside it, a fixed set of apps, each answering one question. Apps are enabled per workspace (like adding Google apps to an account), share the same files, connections, agents and approvals, and hand work to each other.
| App | The question it answers | Holds | Built from |
|---|---|---|---|
| Hoje | What needs me now? | Every decision across apps (messages to approve, lead replies, system writes, team questions, reports), the state of every app, the one setup checklist | Team "Your decisions", setup checks of Team and Go live |
| Rotinas | What runs by itself, and when? | Every routine of the project in one place: the sales funnel on WhatsApp (today's plan, board, leads, rules, the send queue, the business API), the team's recurring work, the scheduled answers of Atendimento; Nova rotina starts any of them | Team → Funil and Team routines, Data & go live → Routines, the Revenue Operations pipeline |
| Equipe | Who works for me, and on what? | Goals for the lead agent, the work board, results, members, flows, routines, budget, log | Team |
| Atendimento | Where do customers talk to my agent, and how well does it answer? | Try it, go live (chat link, WhatsApp, website bubble, API), share, improve from real questions, scheduled answers | Data & go live (try, live, share, improve, routines) |
| Agentes | What do my agents know, and how do they behave? | Agents and their behavior, knowledge files, the context map, tests and versions, run history | Agent Workspace, Lab, World, Context engineering, Studio |
| Conexões | What is plugged in? | The AI that thinks, data sources and business APIs, messaging channels, servers | Data & go live (data, brain), Team brain, WhatsApp line |
How they complement each other:
Conexões ── AI, data, APIs, WhatsApp ──┐
│ │
Agentes ── knowledge & behavior ──► Equipe ── prepares work ──► Hoje ◄── decisions ── Rotinas (funnel)
│ │ ▲
└──────────────► Atendimento ── answers customers ──┘ approved sends ───┘
- Agentes defines what every agent knows; Equipe's members, Atendimento's live agent and the funnel's messages all read it (the funnel messages are knowledge in
knowledge/sales/funil.md). - Conexões gives the others their AI, data and channels: the funnel routine sends through the WhatsApp line and reads the business API; Atendimento answers on WhatsApp and the web; agents look up data.
- Equipe and Rotinas prepare; Hoje is where the owner decides; approved messages leave through the funnel's queue.
- Nothing that leaves the company skips Hoje.
Rules every app follows
- One header, one rail. The top bar shows the workspace and the account; a left rail lists the apps with one color and glyph each, and a badge when something waits. The active app's sections are tabs under its name.
- One readiness model. Hoje owns the checklist (AI connected, business facts complete, channels connected). Apps show a one-line banner that links to the missing step; there are no per-app steppers.
- One status vocabulary. Status chips in the hub and in apps come from the same overview data.
- Language follows the account. The suite chrome is Portuguese or English as the account chooses; engine detail screens that are still English say so in their section label.
- Nothing leaves without the owner. Messages, API writes and publishing wait in Hoje (unchanged guarantees of the funnel and team engines).
- Expert tools are sections, not escapes. Files, the context map, tests and versions and run history are sections of Agentes, named the same in the menu and on the screen.
- Gamification stays in the account. The journey remains under the account menu; it does not compete with work.
- The live agent never answers on the Sales line. Atendimento refuses to go live on the WhatsApp line the funnel sends from: an agent that answers anyone would answer leads without the owner's approval. It uses another number.
Routes
#project/<id>/<app>[/<section>] with app ∈ hoje, equipe, rotinas, atendimento, agentes, pessoas (pessoas, linhas, vinculos), conexoes; the funnel routine is rotinas/funil/<hoje|quadro|leads|regras>, and the earlier vendas/<section> lands there. Earlier routes (#project/<id>/team, …/connect, …/lab, …) keep working and open the matching app section. A project opens on Contexto (#project/<id>/contexto/<recebe|prova|conectar>), including when the optional Kit Vendas is installed. Hoje is reached intentionally from the inbox, a pending-decision notification or the Kit’s operational rail.
The AI on the web and on the desktop
A project whose brain is the desktop's Claude subscription (subscription-cli in launch.yaml) cannot think on the web. Conexões → IA (or Hoje's checklist) lets the owner choose a stand-in there, for example Claude through the account's API key. The stand-in is kept in .seif/brain.json, which never travels with the project files: launch.yaml and the desktop keep the subscription, while the web's team and live agent use the stand-in. Choosing the subscription again on the web removes it.
Why the funnel is a routine
A sales funnel is work that happens by itself on a schedule (the day prepared at 08:00, the queue sent in business hours, the API read every hour), exactly like a team routine or a scheduled answer. Keeping it as its own app split "things that run by themselves" across three places (Vendas, Equipe → routines, Atendimento → scheduled answers). Rotinas puts them together; the funnel keeps its own screens (Hoje, Quadro, Leads, Como funciona) inside its routine.
Routines by area, and the project's API
Rotinas groups every routine by the part of the business it serves: Vendas, Marketing, Administração, Planejamento, Atendimento, Produto (team.yaml area). Nova rotina opens a catalogue per area (the weekly close, the campaign of the week, the plan of the week, welcoming newcomers, a refund alert…); the form shows exactly what the routine will do before it is saved.
A routine starts in one of two ways:
| Trigger | team.yaml | How |
|---|---|---|
| On a schedule | at: "17:00", days: [fri] | once per day at its time, while the office is open |
| When something happens in a connected API | on: { connection, events: [...] } | the office reads the API's event feed every 2 minutes from a kept cursor; the first read only places the cursor; several events become one work item; each event counts once |
and may read API data right before it starts (reads: [{ connection, operation, query, title }]); the data goes with the work, for members in the cloud and on OpenBot alike.
The API is a connection (connections/<id>.yaml, kind http-api) declared operation by operation, plus an optional events: block (the GET with a cursor, the parameter names, the response fields and a label per event type). A member granted Connected APIs (api) may, while working:
- read any GET operation (
api_read; on OpenBot,POST <api_url>of its hand-off, valid while the hand-off is open); - ask for a change (
api_request; on OpenBot,api_requestsin its hand-back). The change waits in Hoje (and on Telegram) as the exact request: method, path, body and why. Approved, it runs once (idempotency key); the result goes back to the member.
Nothing in an API changes without the founder, and the credential stays with the connection (vault/env), sent only to the API's own address.
Enabling apps
A workspace shows the apps its files support. Adicionar app in the rail enables the rest:
| App | Enabled when | Enabling creates |
|---|---|---|
| Hoje, Agentes, Conexões | always (file projects) | — |
| Equipe | team.yaml exists | the team (lead + specialists, knowledge areas) |
| Kit Vendas WhatsApp | installed from the rail | a sales funnel, shared lead list and its embedded operational runtime through the Team office; it remains optional to the Contexto journey |
| Rotinas → funnel | funil/funil.yaml exists | Nova rotina → Funil de vendas: a starter funnel (stages, rules, messages), team/shared/leads.csv and the team it sends through |
| Atendimento | always; goes live when an AI is connected | launch.yaml on first save |
Rotinas → Funil de vendas → Leads → Importar leads takes a pasted table or a CSV (comma, semicolon or tab; a header row names the columns, otherwise name, phone, city, state, segment, notes). Numbers already in the funnel or in the never-contact list are skipped with the reason. With a date, first-stage leads get their first message planned from that day, within the daily limit; without one they wait until scheduled. Importing never sends anything.
Pessoas: a team of people on each project
A project is no longer one person's. The owner brings people in, and each one works with what they were given. Pessoas (a seventh app in the rail) holds who is on the project, the WhatsApp lines and who does what.
| Role | Sees and decides | Manages |
|---|---|---|
| Dono (owner) | everything | people, admins, lines, the project (only the owner deletes it) |
| Admin | everything; may send a message from any line | people (not other admins), lines, everything in the apps |
| Membro | their own: the decisions for them, their contacts and leads, the work done for them, their own conversation with the team | nothing; connects their own line by QR code |
What a member works with (Pessoas → Editar acesso, with ready starts: Comercial, Atendimento, Marketing, Operação): the agents of the team, the WhatsApp lines, the routines, the integrations (API connections), and what they may do: decide what is theirs, write on WhatsApp, approve actions in their integrations, edit the agents' knowledge. A member sees Hoje, Equipe, Rotinas and Pessoas (and Agentes with the knowledge permission); everything else answers 403.
Invitations. Convidar pessoa takes the email, the job and the access; the link (/#convite/<token>, emailed when the server sends mail, otherwise copied) works once, for 14 days, and only for an account with that email. Removing someone keeps their lines on the project, held by nobody, and their contacts on them.
Lines. A project has as many WhatsApp lines as it needs (one Evolution instance each, whatsapp_lines): a label, the person who holds it, the agents that answer on it, and one default line (the company's). The single line a project had before became its default line, held by the owner, with the same instance and webhook token.
The rules (runtime/engine/people.mjs)
- A contact belongs to the first line that talked with them: a message in, a message out (also from the phone), an import or a send. It is kept in
team/shared/carteira.csv(telefone, linha, responsavel, desde, origem). Only an admin moves contacts (Pessoas → Quem faz o quê, or Rotinas → Funil → Leads → Passar para…). - Every message to a contact leaves from its owner's line, whoever prepared it (an agent, a routine, the funnel, a person). Nobody else's line is used by accident. An admin may send one message from another line (the card's Sai por, or Escrever no WhatsApp); the contact stays whose it is.
- A decision goes to the person it is for: the owner of the contact, or the person the work was done for. Admins see all of them (Hoje → Todos · Minhas · <pessoa>). A message that arrives on another person's line is kept in the conversation and goes to the contact's owner ("escreveu para o número de …").
- Work carries the person it is for (
for): a delegation, a routine given to people (it runs once for each of them, with their contacts and line), the Guru's look at a message, the autopilot, a conversation. The agent is told who the people are, who it works for now and the line it speaks from, andcontact_lookupsays whose a contact is. - Each line has its own pace: the daily limit of first messages and the spacing between sends count per line. A queued message whose contact changed hands before it left is cancelled with the reason.
- Nothing else changes: approvals, autopilot, Telegram and OpenBot work as before, now per person. Telegram tells the person a decision is for (their own bot, Conta → Notificações); members see their shared projects there too.
The host is the authority (web/people.mjs: project_members, project_invites, the access check of every project route); it writes .seif/people.json (people, access, lines; never synced to Git) for the engine, which receives the acting person with every command. A project without people (the desktop) behaves exactly as before.
Telegram: the suite in a conversation
Once the founder connects their own bot (Conta → Notificações), the host listens to that one chat (a long poll per account; any other chat is ignored) and the bot becomes a way to run the day:
| The founder | The bot |
|---|---|
| does nothing | sends each decision as a card with buttons; a burst (the day's plan) becomes one message with Revisar agora |
| taps Aprovar e enviar, Não enviar, Agora não, Mudar a etapa, Pedir rascunho ao time, Pular | decides it exactly as Hoje would and sends the next pending card, until the queue is empty |
| replies to a card | answers a lead (each paragraph one message), answers a team question, or approves a new text for a message |
writes /hoje, /vendas, /equipe, /projeto | the decisions per project, the funnel's day (with Preparar o dia), the team's work, the project messages go to |
| writes anything else | it goes to the project's guru; the answer comes back in the chat (also when the guru runs on OpenBot) |
Nothing changes the guarantees: a tap is the founder's decision, and messages still leave only through the send queue.
OpenBot: members that run on the person's computer
Each team member works either on the cloud AI (Conexões → IA) or on OpenBot, the person's own computer, where OpenBot agents run on the person's subscriptions and tools. The choice is per member (Equipe → Membros e rotinas, or Todo o time no OpenBot), kept in .seif/executors.json (never synced), so one does not replace the other.
office ── work for a member on OpenBot ──► hand-off (.seif/team/handoffs/<token>.json: role, instructions, knowledge, brief)
host ── signed webhook (or the bridge) ──► OpenBot agent "SEIF · Equipe" ── works with its own tools
host ◄── POST /openbot/handoff/<token> (once) ── result: report, items, approvals, questions, messages
office ── the result as any member's: the lead reviews (also on OpenBot when it runs there), it flows on, sends wait in Hoje
- Webhook: Conexões → OpenBot takes the routine's public https address and signing secret (sealed on the host). The host signs each request as OpenBot expects (
HMAC-SHA256oftimestamp.id.body) and records whether it was taken. - Bridge (default):
web/openbot-bridge.mjsruns on the person's Mac as a launchd agent (Conexões → OpenBot gives a one-line installer,/openbot/bridge-install.sh). It asks the host for pending hand-offs with the project's bridge address and gives each one to the agent through OpenBot's Local scripts (openbot-cli run), so there is no URL or secret to copy: the agent only needs Local scripts on. Conexões → OpenBot shows whether the bridge checked in and whether OpenBot refused (Local scripts off, app closed). It calls no model. The signed webhook remains an option under Avançado when OpenBot publishes a public address. - Results come back through the bridge: the agent only saves its result as JSON in
~/OpenBot/Shared/seif-devolucoes/<tag>.json(the tag is a hash of the hand-off token, named in the task) and the bridge posts it to that hand-off's own address, then moves it toentregues/(orrecusados/with the reason). The agent never uploads anything itself, so a gate that blocks network uploads from agents (SEIF Gate) stays on. - Cancelling a work closes its open hand-off: a job the founder stopped is never handed to OpenBot later.
- API calls through the bridge: the agent saves
{connection, operation, params, query, body, why}in<tag>.api/<name>.json; within seconds the bridge posts it to the hand-off's API address and writes SEIF's answer in<name>.resposta.json. - Autonomy on an API (
team_writes: directinconnections/<id>.yaml): the founder lets the team change data there without approving each change. A change called through the hand-off, inapi_requestsof a hand-back, or with the cloudapi_requesttool runs once at once; it is kept in Hoje as a decided api-action (auto: true, answer "Autonomia"), the member and the founder get a message, and Telegram says "O time fez na API". Without the line, every change waits for the founder as before. Messages to people keep their own rules (approval or autopilot). - The packet carries the member's resolved context; when it exceeds what a webhook carries, OpenBot fetches it from the same single-use address. A hand-off not handed back in 6 hours fails visibly; one OpenBot refused fails at once.
- OpenBot agents never approve anything: what would leave the company comes back as
approvalsfor the founder.
scripts/verify-openbot.mjs proves the chain with real processes and a stand-in OpenBot webhook.
GitHub: the project and its repository stay the same
Working only in the browser is the normal case, so the host (not anyone's computer) keeps each linked project and its GitHub repository the same (web/git-sync.mjs, Conexões → GitHub):
| Change | How it travels | When |
|---|---|---|
An edit in the app, a team report, the funnel's leads, a desktop seif cloud sync | committed (author: the project's owner; committer: SEIF Suite) and pushed | under a minute after it settles |
| A push to GitHub (a Claude Code session, an edit on github.com, a PR merged) | the repository's push webhook pokes /github/push/<token>; the host fetches and merges | seconds |
| Anything missed (webhook not set, the host restarted) | the timer | every 5 minutes |
- Access: one ed25519 deploy key per project, made on the host and sealed with the project's vault key, with write access to that repository only. GitHub's SSH host keys are pinned. With a fine-grained token (used once, never stored) the host adds the key and the webhook itself; without one, the screen shows the two steps.
- History: a git directory per project under
<data>/git/, outside the project folder (the project folder is its work tree)..seif/and.workstation/(the app's own state and secrets) never go to Git, and a repository that tracks them is refused. The repository's.gitignoreapplies; files over 50 MB stay out; symlinks are plain files. - Conflicts: the first sync deletes nothing: a file on one side only goes to the other, and for a file on both sides the newer edit wins. Later, the same file changed on both sides between two syncs keeps the app's version. The other version is always saved under
.seif/git-sync/kept/<time>/{app,github}/and listed in Conexões → GitHub. - Hoje shows the state on the Conexões card ("GitHub: sincronizado").
What is no longer needed: a copy of the project on another computer to carry changes to GitHub (the Missão CNH scripts/sincronizar-app.sh job on the mini). A local clone is just a clone: git pull, work, git push.
Versions: development and production
A project of files is in development until its first version is published, then in production · vN (the chip next to the project name). Agentes → Versões:
- What changed since vN: the files of the product (knowledge, agents, the funnel, the team and its routines, connections, the service agent, tests). Day-to-day data (team/: leads, conversations, reports) is not versioned this way; it keeps flowing to GitHub as it changes.
- Test and publish vN+1: runs the context tests (shown before publishing; failing tests ask for a confirmation and are recorded), sends everything to GitHub, writes the entry in
VERSOES.mdand tags the commitvN+1. - Go back to vN: restores the product's files as they were in vN (team/ stays as it is); the restore is itself a change to publish.
- The per-agent pipeline (Design → Build → Deploy, for single-agent projects) stays one link away.
Routines, one page each; materials
rotinas/<id>: when it runs next, every run with its status, report and what it led to, the decisions it waits on (decided right there), what it reads from the API (with a read test that starts nothing), and a note for its next run (it goes once). Hoje shows the team's agenda for the day.team/materiais/holds the pieces messages send (PNG, JPG, WEBP, GIF, PDF, MP4 up to 16 MB). A message sends one when it is the line[material: team/materiais/<file>]with the caption below. Rotinas → Funil de vendas → Materiais uploads and previews them; the funnel checks that the piece exists; approval cards show it; WhatsApp sends it withsendMedia. Members see the list in their work; members on OpenBot hand back art infiles.
The Central, the listener and the team's memory
Hoje is the Central for a project with a team: the founder's desk.
- The Guru at the top: ask anything, tell who someone is, change a priority. It delegates and keeps what it is told.
- A persistent Executive Canvas holds the views the founder wants, arranged their way and saved per project (
team/central/canvas.json, versioned like everything else). Each view references live operational state — it never keeps a copy — so if the file is lost the work is untouched and a default canvas returns. The founder adds, reorders, collapses or removes views from a small typed catalogue: the day's flow, the decisions (filterable), the team roster, today's agenda, project health, a live metric (pending decisions, work in progress, done today, leads, spend, people), recent results, the team's memory, or one person's card. The Guru changes the canvas when asked ("show the decisions next to the team") through a validated structured operation — add, remove, move, configure or reset — never arbitrary code; an unknown view or a missing reference is refused with a reason. - The day's demands flow as cards through four lanes, linked as they lead to each other: Chegou (a message just arrived; the Guru is looking) → Precisa de você → O time está fazendo → Feito hoje. The flow is one view on the canvas. A card opens on the side with everything to decide or guide — including the decision's evidence (why it waits, what the team found, the alternatives, what is still unknown, the Guru's recommendation and a link to the report); what the founder decides there is what actually happens, confirmed by the system. Without a selection the side shows the day's agenda, health and apps.
- The health strip (and Hoje → Saúde) shows the office, the WhatsApp line, OpenBot, the API and GitHub.
The executive board (Hoje). Written for someone who runs a business, not for a developer; nothing is shown twice and details open over the board (Esc closes them):
- O Guru speaks first: the day in sentences (who wrote, what the team delivered, what waits, what comes next), the next best actions as buttons, the project's health as one sentence in plain words ("Assistentes no seu Mac", "Sistema da empresa", "Backup e histórico"), and the conversation with the Guru right there.
- Os números de hoje: decisions waiting, people who wrote, deliveries, leads, messages sent.
- Sua decisão: one decision at a time, the most urgent first (a message, then a question, then the rest), with the Guru's suggestion and the direct buttons; "Ver tudo" opens the full card.
- Seu time agora: the members as people saying what they do (or that they wait for the Mac); a click asks them for something.
- A história do dia: each demand as a chain of steps (arrived → the Guru → you → the team → done).
The board is the canvas (team/central/canvas.json): Organizar o painel reorders, adds or removes views, and the Guru can arrange it on request; a board still on the first default moves to this one.
The WhatsApp listener (24/7). Every message on the project's line:
- is recorded with its contact (
team/contatos/<number>.md: name, relation, mode, notes, the last messages of someone outside the funnel); - unless the contact is silencio, becomes a card with who the person is for the project, and the Guru looks at it right away (a triage work item): who it is, whether it is business, what the founder should do, and a draft reply for approval. The suggestion appears on the card and on Telegram;
- the founder answers, tells the Guru how to go on (Guru, siga assim, or a reply starting with
guru:on Telegram), notes something about the person (Anotar,nota:), marks them personal (never raised again), or puts them on autopilot: the team answers by itself, through the send queue, only when the message passes the funnel's rules (otherwise it waits), and the founder is told.
Memory. Members have contact_lookup, contact_note and remember (members on OpenBot hand back notes and memory). team/memoria/<topic>.md keeps dated facts; every member starts its work with the topics and their latest facts. Both are files of the project, so they go to GitHub and stay out of a version (team/ is day-to-day data).
Self-healing (web/health.mjs, every minute): an office that stopped by itself reopens (one the founder closed stays closed); work OpenBot never handed back or that a dead process held is put back or failed with the reason; problems reach the founder once when they start and once when they are solved.
Publishing SEIF itself
Every merge to main of seif-context-workstation is tested and published by a GitHub Actions runner on the production VM (.github/workflows/deploy.yml; it connects out to GitHub, so nothing new is exposed and no SSH key is a secret). The unit tests run in the running image (scripts/ci-vm-tests.sh, CPU-limited); the publish (scripts/deploy-from-checkout.sh) keeps the VM's .env, data volume and installed dependencies, and goes through the same health check and rollback as before. Two cases still need scripts/deploy-cloud-vm.sh from a machine with the private packages (.tools/packages): a changed runtime/package-lock.json, and new course videos (Git LFS).
Revenue Operations in the suite
seif-revenue-ops proved the operating rules a sales operation needs: deterministic code moves the pipeline, language work is prepared under each role's context, every outward action is approved against its exact payload, moves need evidence, and revenue counts only with proof. The sales-funnel routine is where those rules run for any business in the web product:
| Revenue Operations | In the suite |
|---|---|
| Pipeline states and transitions | The funnel stages of funil/funil.yaml, moved by replies, API reads or the owner |
| Approval bound to the exact text, channel and recipient | Hoje: what is approved is exactly what the queue sends, to that number |
| Scout / Sales roles under their own context | Equipe members (Prospector, Sales strategist), each an agent of the project |
| Owner-recorded buyer events | Mudar de etapa on a lead, with the conversation beside it |
| Evidence before a move | The funnel's API reads (sincronizar) move a lead only on a field that proves it |
The repository stays the operation SEIF runs for its own reliability services and the Radar product (radar.seifprotocol.com). Its CLI is not needed to run a funnel in the suite.
Verification
scripts/verify-web-suite.mjs drives the suite in a real browser against a local host: every app and section renders, legacy routes land in the right app, the rail badges match the decisions, and no page error occurs.