Espaços de trabalho e isolamento
O que é um espaço de trabalho?
Seção intitulada “O que é um espaço de trabalho?”Um espaço de trabalho é o tenant de isolamento de nível superior no Control Center. Ele agrupa agentes, repositórios, espaços, tickets, memória, pipelines e membros em um contexto delimitado. Tudo o que acontece dentro de um espaço de trabalho permanece dentro dele.
Um espaço de trabalho típico corresponde a um projeto ou a uma base de código. Você pode ter espaços de trabalho separados para “api-service”, “frontend-v2” e “infrastructure”.
Dados com escopo de espaço de trabalho
Seção intitulada “Dados com escopo de espaço de trabalho”As linhas de um espaço de trabalho ficam no arquivo SQLite do próprio espaço de trabalho, em <dataDir>/<workspaceId>/workspace.db. Cada espaço de trabalho recebe um diretório em vez de um arquivo solto, porque um espaço de trabalho acumula mais do que um banco de dados — worktrees por conversa, os arquivos de agente e de skill, credenciais de bot de chat — e dar a ele uma pasta significa que tudo isso vive e é excluído junto.
| Entidade | Escopo |
|---|---|
| Agentes | Pertencem a exatamente um espaço de trabalho |
| Repositórios | Registrados em um espaço de trabalho (veja abaixo) |
| Espaços, conversas e mensagens | Com escopo de espaço de trabalho |
| Tickets, projetos, planos, orquestrações | Com escopo de espaço de trabalho |
| Fatos de memória, políticas, domínios, concessões de acesso | Com escopo de espaço de trabalho |
| Execuções de pipeline, modelos, gatilhos | Com escopo de espaço de trabalho |
| Estado de pull request, espaços de revisão, coortes de revisão | Com escopo de espaço de trabalho |
| Logs de execução de agente e memória de trabalho | Com escopo de espaço de trabalho |
| Membros, convites, concessões por repositório | Com escopo de espaço de trabalho |
| Símbolos e arestas do grafo de código | Com escopo por repoId dentro do arquivo do espaço de trabalho |
A maioria dessas linhas carrega uma coluna workspaceId; arquivos de banco de dados separados impõem o isolamento. Veja a invariante de isolamento abaixo.
Repos têm escopo de espaço de trabalho; a identidade entre espaços de trabalho é por caminho
Seção intitulada “Repos têm escopo de espaço de trabalho; a identidade entre espaços de trabalho é por caminho”Uma linha de repo vive no arquivo de banco de dados do próprio espaço de trabalho — o arquivo é o escopo, então a tabela não tem coluna workspaceId nem tabela de junção.
Você adiciona um repo a um espaço de trabalho em Configurações → Espaço de trabalho → Repositórios. Registrar o mesmo checkout em dois espaços de trabalho cria duas linhas independentes, com dois ids; a identidade do repo entre espaços de trabalho é pelo caminho no sistema de arquivos (ou pelo owner/name do GitHub), nunca pelo id.
O registro é rígido: o caminho precisa estar dentro de uma árvore de trabalho do git, precisa ter um remote origin e esse remote precisa apontar para um forge compatível (github.com, gitlab.com ou bitbucket.org). O forge é lido do remote e armazenado no repo, então um espaço de trabalho pode conter repos dos três. Qualquer outra coisa é rejeitada. O navegador de pastas de onde você escolhe lista o sistema de arquivos do host do servidor, restrito à lista de permissões --repo-roots do servidor (que usa por padrão o diretório home do usuário do servidor).
Remover um repositório de um espaço de trabalho exclui a linha de imediato e propaga em cascata seus símbolos de código, arestas, arquivos, checkpoints de índice e concessões por membro. O checkout no disco não é tocado.
O grafo de código vive no mesmo arquivo, indexado por repoId, porque espaços de trabalho diferentes podem ter o mesmo repositório em branches diferentes com código diferente.
A invariante de isolamento
Seção intitulada “A invariante de isolamento”Vazamentos de dados entre espaços de trabalho são tratados como bugs. O isolamento é estrutural, imposto em vários níveis:
- Camada de banco de dados. Cada espaço de trabalho tem seu próprio arquivo SQLite, entregue por
WorkspaceDatabaseManager.of(workspaceId). Um banco de dados de espaço de trabalho não declarausers,workspacesnem as tabelas de qualquer outro espaço de trabalho, então uma leitura entre espaços de trabalho não é um bug que você consiga escrever — ela não compila. Os repositórios resolvem seu DAO a cada chamada em vez de guardar um em cache e, como todo método de repositório recebe umworkspaceIdobrigatório, o espaço de trabalho nunca pode ser inferido nem assumido por padrão. - O id do espaço de trabalho é um segmento de caminho. Como o id se torna um nome de diretório, ele precisa corresponder a um padrão seguro de segmento único (início alfanumérico, depois alfanuméricos, pontos, sublinhados, hífens; sem
..). Os ids são UUIDs em todo o produto. Qualquer outra coisa lança uma exceção em vez de ser sanitizada — essa é a proteção contra path traversal, e ela falha de forma ruidosa em vez de gravar os dados de um espaço de trabalho em um caminho escolhido por outra pessoa. - Defesa em profundidade. As colunas
workspaceIdcontinuam lá e continuam sendo gravadas. Redundantes dentro de um arquivo, elas mantêm inalterados os gatilhos do feed de sincronização, os índices FTS e os formatos de linha existentes, e tornam um arquivo autodescritivo quando ele é inspecionado por conta própria — que é no que a exportação e a importação se apoiam. - Camada de domínio. Serviços que alteram entidades por id validam
entity.workspaceId == workspaceIdem um único ponto de estrangulamento antes de prosseguir e lançamWorkspaceMismatchExceptionquando não coincidem — a falha ruidosa para um id que chegou do contexto errado. Negar de forma ruidosa importa: um no-op silencioso esconde o bug e prosseguir vaza. - Camada RPC. O dispatcher de repo-RPC é o ponto de estrangulamento. Toda op com escopo de espaço de trabalho precisa carregar
workspace_idnos próprios argumentos — não existe um “espaço de trabalho atual” por sessão que possa vazar, e um id desconhecido é recusado como não encontrado antes de qualquer coisa abrir um banco de dados, então um id ruim não pode materializar umworkspace.dbfantasma. Ops genuinamente globais (o feed de notícias, a fila da frota) se declaram sem escopo como uma decisão explícita e revisada. As ferramentas MCP seguem a mesma regra: qualquer ferramenta que toque em dados com escopo de espaço de trabalho exigeworkspace_id. - O fan-out entre espaços de trabalho é enumerável. Responder a uma pergunta sobre vários espaços de trabalho significa abrir vários bancos de dados. Esse fan-out fica confinado a um único auxiliar,
CrossWorkspaceQueries, de modo que a lista completa do que cruza legitimamente a fronteira vive nos pontos de chamada de um único arquivo, em vez de se difundir por trás de comentários de documentação. Esses pontos de chamada são: agregação de todo o servidor, reconciliadores de inicialização, varreduras de retenção e GC, backup, roteadores de eventos — e a consulta de associação abaixo. - Acesso somente por ID não é suficiente. Consultar uma entidade pelo seu UUID não prova que ela pertence ao espaço de trabalho de quem chama. A divisão de arquivos torna o arquivo errado inalcançável; a validação da camada de domínio captura um id errado que chega por um arquivo legítimo.
O que concede acesso é a associação, não a chave de emparelhamento
Seção intitulada “O que concede acesso é a associação, não a chave de emparelhamento”Ter uma credencial de dispositivo autentica um dispositivo. Ela não autoriza nada dentro de um espaço de trabalho. Toda op com escopo de espaço de trabalho resolve a função de associação de quem chama e aplica um piso derivado do tipo da op — leitura exige guest, uma mutação exige member, uma operação destrutiva exige admin — e as ops que expõem conteúdo de repo também verificam a concessão por repositório de quem chama. Uma chave de emparelhamento válida sem associação recebe Not a member of this workspace.
A consequência para o isolamento é elegante: as linhas de associação ficam no arquivo do próprio espaço de trabalho, então “quem está neste espaço de trabalho?” é uma leitura comum com escopo. A pergunta inversa — “em quais espaços de trabalho eu estou?” — está, por definição, espalhada entre arquivos, então é um dos poucos fan-outs CrossWorkspaceQueries sancionados e é o que o seletor de espaços de trabalho executa antes de qualquer espaço de trabalho ter sido escolhido.
Veja Multijogador para a escada de funções e as concessões por repositório.
O registro global
Seção intitulada “O registro global”Nem tudo tem escopo de espaço de trabalho. Um segundo banco de dados, <dataDir>/global.db, guarda o que é genuinamente de todo o servidor:
- o registro de espaços de trabalho, para que o alternador possa listar todos os espaços de trabalho sem abrir um único arquivo de espaço de trabalho — e para que o nome, o logo, o proprietário, a ordem no manual e o marcador de exclusão lógica de um espaço de trabalho fiquem fora do arquivo que descrevem;
- identidade: usuários, preferências de usuário e dispositivos emparelhados, porque uma pessoa é um usuário em todos os espaços de trabalho e um dispositivo emparelhado sobrevive à exclusão de um espaço de trabalho;
- a fila da frota (workers, jobs, log de alocação), cujo agendador compara a fila inteira com todos os workers a cada ciclo;
- o feed de notícias, que é por usuário (não por espaço de trabalho) — adicionar um feed acompanha você em todos os espaços de trabalho;
workspace_routes, o índice de pré-autenticação que responde “qual espaço de trabalho é dono desta chave?” para pontos de entrada que chegam sem nada além de um segredo ou um id opaco (um hash de convite, um token de webhook, um deep link) e nenhum espaço de trabalho. Uma ausência ali é um não encontrado; deliberadamente não há fallback de varredura;- configurações e identidade de toda a instalação: o id da instalação, configurações de nível de host, conexões SSO e políticas de ação gerenciadas (um limite de toda a instalação que só pode restringir as barreiras dos espaços de trabalho).
A inicialização abre apenas este arquivo. Os arquivos de espaço de trabalho são abertos sob demanda no primeiro toque, então o custo de partida permanece constante por mais histórico que os espaços de trabalho acumulem, e o quick_check por arquivo é pago no primeiro uso, e não no caminho até o banner de pronto.
Um arquivo de espaço de trabalho carrega apenas um workspace_meta de linha única para se autodentificar (seu id, a instalação que o criou, a versão de esquema com que ele foi criado e quando). Tudo o que descreve um espaço de trabalho está no registro.
Criar um espaço de trabalho
Seção intitulada “Criar um espaço de trabalho”Criar um espaço de trabalho faz mais do que inserir uma linha no registro. Em uma única operação, o servidor marca o usuário criador como ownerUserId, registra a associação desse usuário na função de proprietário e publica um evento de domínio WorkspaceCreated. Os listeners desse evento então semeiam, de forma idempotente e em segundo plano:
- um agente CEO mais quatro especialistas —
qa,architect,engineer,librarian— com os especialistas se reportando ao CEO; - os modelos de pipeline integrados e seus gatilhos (gatilhos de evento e manuais vêm habilitados; os agendados são opcionais, exceto a varredura diária de GC de worktrees);
- as suítes de avaliação iniciais.
Isso acontece para todos os espaços de trabalho, não apenas o primeiro. Os agentes semeados são criados sem adaptador, então rodam no Control Center (built-in) com o modelo padrão da Anthropic (claude-opus-4-8, a menos que você fixe outro) até você definir um adaptador e um modelo por agente em Configurações → Espaço de trabalho → Agentes. Veja O modelo de agentes.
A gravação da associação do proprietário importa mais do que parece: sem ela, o espaço de trabalho recém-criado não teria membros e toda chamada com escopo de espaço de trabalho que o criador fizesse em seguida seria negada.
Excluir, exportar, importar
Seção intitulada “Excluir, exportar, importar”Excluir um espaço de trabalho marca a linha do registro e desvincula o diretório. O espaço de trabalho desaparece de todas as listas e consultas. A linha do registro permanece (com exclusão lógica) para que o id ainda seja conhecido pelo backup e pela manutenção, mas workspace.delete descarta imediatamente o diretório desse espaço de trabalho — banco de dados, worktrees, arquivos de agente e o resto — por meio de WorkspaceDatabaseManager.dropAndClose. Apenas o proprietário do espaço de trabalho pode excluí-lo.
Como um espaço de trabalho é um arquivo, entregar um espaço de trabalho é uma operação de arquivo, e não um dump tabela por tabela:
workspace.exporté um únicoVACUUM INTO— um snapshot consistente e desfragmentado, tirado dentro de uma transação de leitura enquanto o servidor continua atendendo.workspace.importadota um arquivo desses, substituindo tudo o que o espaço de trabalho de destino contém no momento. Oworkspace_metaembutido permite que uma importação distinga “meu próprio arquivo, readotado” de “um arquivo de outra instalação” (o segundo é permitido, mas registrado em log em vez de invisível).server.backupNowtira um snapshot da instalação inteira em um diretório com data e hora que espelha o diretório de dados ativo —manifest.json,global.dbe um<workspaceId>/workspace.dbpor espaço de trabalho — de modo que restaurar é copiá-lo de volta.server.listBackupslê esse diretório de volta, do mais recente para o mais antigo, com o tamanho e a lista de espaços de trabalho de cada snapshot. Um snapshot cujo manifesto está ausente ou nomeia arquivos que não existem ainda é relatado, marcado como incompleto — escondê-lo é como um operador passa a acreditar que tem um backup que não tem.
As operações de backup ficam em Configurações → Servidor → Backup e restauração: Fazer backup agora tira um snapshot da instalação, a lista mostra quais snapshots estão completos e permite que o proprietário da instalação exclua um após confirmação, e cada espaço de trabalho oferece exportação e importação. O pipeline integrado Workspace backup pega apenas o banco de dados desse espaço de trabalho em um agendamento semanal e exclui os próprios backups mais antigos que a idade de retenção configurada. Restaurar um espaço de trabalho a partir de um snapshot da instalação é apontar workspace.import para o <workspaceId>/workspace.db do snapshot; restaurar uma instalação inteira continua sendo uma cópia de volta do diretório do snapshot com o servidor parado.
O que nenhuma delas carrega é o resto do diretório do espaço de trabalho. Um espaço de trabalho acumula mais do que um banco de dados — imagens coladas, arquivos de skill e de agente, credenciais de chat, worktrees — e a exportação e a importação movem o arquivo, então tudo o que está ao lado dele fica onde está. Isso é proposital para credenciais e descartável para worktrees; para o resto, é um limite que vale conhecer, e não um recurso. A referência de backup tem a tabela completa.
Mover um backup entre o servidor e seu dispositivo
Seção intitulada “Mover um backup entre o servidor e seu dispositivo”Toda op acima fala em caminhos no servidor, o que só é uma resposta completa quando o servidor é a sua própria máquina. Três rotas HTTP assinadas — /backup/workspace, /backup/snapshot e /backup/restore — carregam os bytes para todas as outras topologias, na mesma faixa autenticada que o proxy de mídia e o armazenamento de imagens já usam. Na página, isto é um botão Baixar ao lado de cada exportação e de cada snapshot (você escolhe onde ele cai) e Escolher um arquivo e enviar para restaurar a partir de um arquivo que está na máquina que você usa. O upload é o que funciona quando o servidor não é a sua máquina: workspace.import precisa que o arquivo já esteja no host, e é assim que ele chega lá.
Três propriedades valem a pena conhecer:
- Um download cria uma cópia nova e o servidor não fica com nada dela. Baixar não é “buscar o arquivo que o botão de exportar criou” — ele exporta de novo, transmite isso e exclui. A resposta é
no-storecomAccept-Ranges: nonepelo mesmo motivo: um intervalo retomado juntaria duas exportações diferentes em um arquivo que parece válido e não é. - Um upload é transmitido para o disco, nunca bufferizado, nas duas pontas, e a cópia preparada é excluída em todos os caminhos de saída — inclusive em uma recusa. Um banco de dados de espaço de trabalho não é uma captura de tela.
- Uma conexão via relay não tem origem HTTP, então os controles de transferência ficam desabilitados nela, com uma observação explicando por quê. Tudo o que fala em caminhos do lado do servidor continua funcionando pelo relay; só as faixas de bytes precisam de uma conexão direta.
Vários espaços de trabalho
Seção intitulada “Vários espaços de trabalho”Você pode executar vários espaços de trabalho lado a lado. Cada um opera de forma independente: agentes em um espaço de trabalho não podem enviar mensagens a agentes de outro, não podem ler a memória de outro espaço de trabalho nem ver seus tickets. A resolução de destinatários para mensagens entre agentes é exata e nunca cruza um espaço de trabalho.
Não existe um painel entre espaços de trabalho. A superfície de análise em /workspaces/:workspaceId/observability assina um feed global delimitado de execuções recentes e imediatamente o restringe ao espaço de trabalho ativo, então o que você vê ali é um espaço de trabalho por vez. As únicas superfícies genuinamente multi-espaço de trabalho que uma pessoa toca são o seletor de espaços de trabalho e o alternador.
Um limite prático que vale conhecer: um espaço de trabalho que alguém está usando permanece aberto — não há LRU. Passando de 32 deles, o servidor avisa em vez de recusar, porque cada arquivo aberto mantém um isolate em segundo plano e um cache de páginas. O fan-out entre espaços de trabalho abre arquivos transitoriamente e os fecha depois, se nada mais os tiver reivindicado.
Conceitos relacionados
Seção intitulada “Conceitos relacionados”- Multijogador: associação, funções e concessões por repositório — a metade de acesso do isolamento
- O modelo de agentes: agentes pertencem a exatamente um espaço de trabalho
- Memória e conhecimento: a memória tem escopo de espaço de trabalho
- Arquitetura: onde os bancos de dados ficam na divisão cliente/servidor
- Fazer backup e restaurar: tirar um snapshot, mover um espaço de trabalho, manter cópias em outro lugar
- Backup, exportação e importação: todas as operações, rotas, campos de manifesto e limites
- Adicionar repositórios: registrar um checkout em um espaço de trabalho