Espacios de trabajo y aislamiento
¿Qué es un espacio de trabajo?
Sección titulada «¿Qué es un espacio de trabajo?»Un espacio de trabajo es el inquilino de aislamiento de nivel superior de Control Center. Agrupa agentes, repositorios, espacios, tickets, memoria, pipelines y miembros en un contexto acotado. Todo lo que ocurre dentro de un espacio de trabajo se queda dentro de él.
Un espacio de trabajo típico se corresponde con un proyecto o una base de código. Puede que tengas espacios de trabajo distintos para «api-service», «frontend-v2» e «infrastructure».
Datos con ámbito de espacio de trabajo
Sección titulada «Datos con ámbito de espacio de trabajo»Las filas de un espacio de trabajo viven en el propio archivo SQLite de ese espacio de trabajo, en <dataDir>/<workspaceId>/workspace.db. Cada espacio de trabajo recibe un directorio en lugar de un archivo suelto, porque un espacio de trabajo acumula más que una base de datos —worktrees por conversación, los archivos de agentes y skills, credenciales de bots de chat— y darle una carpeta significa que todo eso vive y se elimina junto.
| Entidad | Ámbito |
|---|---|
| Agentes | Pertenecen a exactamente un espacio de trabajo |
| Repositorios | Se registran en un espacio de trabajo (ver más abajo) |
| Espacios, conversaciones y mensajes | Con ámbito de espacio de trabajo |
| Tickets, proyectos, planes, orquestaciones | Con ámbito de espacio de trabajo |
| Hechos de memoria, políticas, dominios, concesiones de acceso | Con ámbito de espacio de trabajo |
| Ejecuciones de pipeline, plantillas, disparadores | Con ámbito de espacio de trabajo |
| Estado de las pull requests, espacios de revisión, cohortes de revisión | Con ámbito de espacio de trabajo |
| Registros de ejecución de agentes y memoria de trabajo | Con ámbito de espacio de trabajo |
| Miembros, invitaciones, concesiones por repositorio | Con ámbito de espacio de trabajo |
| Símbolos y aristas del grafo de código | Con ámbito de repoId dentro del archivo del espacio de trabajo |
La mayoría de estas filas llevan una columna workspaceId; los archivos de base de datos independientes imponen el aislamiento. Consulta la invariante de aislamiento que viene más abajo.
Los repos tienen ámbito de espacio de trabajo; la identidad entre espacios de trabajo es por ruta
Sección titulada «Los repos tienen ámbito de espacio de trabajo; la identidad entre espacios de trabajo es por ruta»La fila de un repo vive en el propio archivo de base de datos de su espacio de trabajo —el archivo es el ámbito, así que la tabla no tiene columna workspaceId ni tabla de unión.
Añades un repo a un espacio de trabajo en Ajustes → Espacio de trabajo → Repositorios. Registrar el mismo checkout en dos espacios de trabajo crea dos filas independientes con dos identificadores; la identidad de un repo entre espacios de trabajo es por ruta del sistema de archivos (o por propietario/nombre de GitHub), nunca por identificador.
El registro es estricto: la ruta debe estar dentro de un árbol de trabajo de git, debe tener un remoto origin y ese remoto debe apuntar a un host de código compatible (github.com, gitlab.com o bitbucket.org). El host de código se lee del remoto y se guarda en el repo, así que un espacio de trabajo puede contener repos de los tres. Cualquier otra cosa se rechaza. El explorador de carpetas en el que eliges lista el sistema de archivos del host del servidor, limitado a la lista de rutas permitidas de --repo-roots del servidor (que de forma predeterminada es el directorio personal del usuario del servidor).
Quitar un repositorio de un espacio de trabajo elimina la fila sin más y propaga el borrado a sus símbolos de código, aristas, archivos, puntos de control del índice y concesiones por miembro. El checkout en disco queda intacto.
El grafo de código vive en el mismo archivo, indexado por repoId, porque distintos espacios de trabajo pueden tener el mismo repositorio en ramas diferentes con código distinto.
La invariante de aislamiento
Sección titulada «La invariante de aislamiento»Las filtraciones de datos entre espacios de trabajo se tratan como errores. El aislamiento es estructural y se impone en varios niveles:
- Capa de base de datos. Cada espacio de trabajo tiene su propio archivo SQLite, que entrega
WorkspaceDatabaseManager.of(workspaceId). Una base de datos de espacio de trabajo no declarausers,workspacesni las tablas de ningún otro espacio de trabajo, así que una lectura entre espacios de trabajo no es un error que puedas llegar a escribir: no compila. Los repositorios resuelven su DAO en cada llamada en lugar de cachear uno y, como todo método de repositorio recibe unworkspaceIdobligatorio, el espacio de trabajo nunca se puede inferir ni dejar por omisión. - El identificador del espacio de trabajo es un segmento de ruta. Como el identificador se convierte en un nombre de directorio, debe coincidir con un patrón seguro de un único segmento (empieza por un alfanumérico y después alfanuméricos, puntos, guiones bajos y guiones; sin
..). En todo el producto los identificadores son UUID. Cualquier otra cosa lanza una excepción en lugar de sanearse —esa es la protección contra el salto de ruta, y falla de forma ruidosa en vez de escribir los datos de un espacio de trabajo en una ruta que eligió otra persona. - Defensa en profundidad. Las columnas
workspaceIdsiguen ahí y se siguen escribiendo. Redundantes dentro de un archivo, mantienen sin cambios los disparadores del feed de sincronización, los índices FTS y las formas de fila existentes, y hacen que un archivo se describa a sí mismo cuando se inspecciona por separado —que es en lo que se apoyan la exportación y la importación. - Capa de dominio. Los servicios que mutan entidades por identificador validan
entity.workspaceId == workspaceIden un único punto de control antes de continuar y lanzanWorkspaceMismatchExceptionsi no coinciden —el fallo ruidoso para un identificador que llegó desde el contexto equivocado. Denegar de forma ruidosa importa: un no-op silencioso oculta el error y continuar filtra. - Capa RPC. El despachador de RPC de repos es el punto de control. Toda operación con ámbito de espacio de trabajo debe llevar
workspace_iden sus propios argumentos —no hay ningún «espacio de trabajo actual» por sesión que se pueda filtrar, y un identificador desconocido se rechaza como no encontrado antes de que nada abra una base de datos, así que un identificador erróneo no puede materializar unworkspace.dbfantasma. Las operaciones genuinamente globales (las noticias, la cola de flota) se declaran sin ámbito como una decisión explícita y revisada. Las herramientas MCP siguen la misma regla: cualquier herramienta que toque datos con ámbito de espacio de trabajo requiereworkspace_id. - La expansión entre espacios de trabajo es enumerable. Responder a una pregunta sobre varios espacios de trabajo implica abrir varias bases de datos. Esa expansión queda confinada a un único ayudante,
CrossWorkspaceQueries, de modo que la lista completa de cosas que cruzan legítimamente la frontera vive en los puntos de llamada de un solo archivo en lugar de difuminarse tras comentarios de documentación. Esos puntos de llamada son: la agregación de todo el servidor, los reconciliadores de arranque, los barridos de retención y de recolección de basura, la copia de seguridad, los enrutadores de eventos — y la consulta de pertenencia que viene más abajo. - El acceso solo por identificador no basta. Buscar una entidad por su UUID no demuestra que pertenezca al espacio de trabajo de quien llama. La separación de archivos hace inalcanzable el archivo equivocado; la validación de la capa de dominio atrapa un identificador erróneo que llegue a través de un archivo legítimo.
La pertenencia, y no la clave de emparejamiento, es lo que concede el acceso
Sección titulada «La pertenencia, y no la clave de emparejamiento, es lo que concede el acceso»Tener una credencial de dispositivo autentica a un dispositivo. No autoriza nada dentro de un espacio de trabajo. Toda operación con ámbito de espacio de trabajo resuelve el rol de pertenencia de quien llama e impone un mínimo derivado del tipo de operación —una lectura necesita guest, una mutación necesita member y una operación destructiva necesita admin—, y las operaciones que exponen contenido de repos comprueban además la concesión por repositorio de quien llama. Una clave de emparejamiento válida sin pertenencia recibe Not a member of this workspace.
La consecuencia para el aislamiento es elegante: las filas de pertenencia viven en el archivo del propio espacio de trabajo, así que «¿quién está en este espacio de trabajo?» es una lectura con ámbito corriente. La pregunta inversa —«¿en qué espacios de trabajo estoy?»— está repartida entre archivos por definición, así que es una de las pocas expansiones de CrossWorkspaceQueries autorizadas, y es lo que ejecuta el selector de espacios de trabajo antes de que se haya elegido ninguno.
Consulta Multijugador para la jerarquía de roles y las concesiones por repositorio.
El registro global
Sección titulada «El registro global»No todo tiene ámbito de espacio de trabajo. Una segunda base de datos, <dataDir>/global.db, contiene lo que es genuinamente de todo el servidor:
- el registro de espacios de trabajo, para que el conmutador pueda listar todos los espacios de trabajo sin abrir un solo archivo de espacio de trabajo —y para que el nombre, el logotipo, el propietario, el orden manual y el marcador de borrado lógico de un espacio de trabajo vivan fuera del archivo que describen;
- la identidad: usuarios, preferencias de usuario y dispositivos emparejados, porque una persona es un único usuario en todos los espacios de trabajo y un dispositivo emparejado sobrevive al borrado de un espacio de trabajo;
- la cola de flota (workers, trabajos, registro de colocación), cuyo planificador contrasta toda la cola con cada worker en cada ciclo;
- las noticias, que son por usuario (no por espacio de trabajo) —añadir una fuente te sigue a todos los espacios de trabajo;
workspace_routes, el índice previo a la autenticación que responde a «¿qué espacio de trabajo es dueño de esta clave?» para puntos de entrada que llegan solo con un secreto o un identificador opaco (un hash de invitación, un token de webhook, un enlace directo) y sin espacio de trabajo. Un fallo ahí es un no encontrado; deliberadamente no hay ningún recorrido de reserva;- ajustes e identidad de toda la instalación: el identificador de la instalación, los ajustes de nivel de host, las conexiones SSO y las políticas de acciones gestionadas (un tope de toda la instalación que solo puede endurecer las barandillas de los espacios de trabajo).
El arranque abre solo este archivo. Los archivos de los espacios de trabajo se abren de forma perezosa en el primer acceso, así que el coste de inicio se mantiene constante por mucha historia que acumulen los espacios de trabajo, y el quick_check de cada archivo se paga en el primer uso y no en el camino hasta el aviso de preparado.
Un archivo de espacio de trabajo solo contiene una workspace_meta de una sola fila para identificarse a sí mismo (su identificador, la instalación que lo creó, la versión del esquema con la que se creó y cuándo). Todo lo descriptivo de un espacio de trabajo está en el registro.
Crear un espacio de trabajo
Sección titulada «Crear un espacio de trabajo»Crear un espacio de trabajo hace más que insertar una fila en el registro. En una sola operación, el servidor marca al usuario que lo crea como ownerUserId, registra la pertenencia de ese usuario con el rol de propietario y publica un evento de dominio WorkspaceCreated. Los escuchadores de ese evento siembran entonces, de forma idempotente y en segundo plano:
- un agente CEO y cuatro especialistas —
qa,architect,engineer,librarian—, que reportan al CEO; - las plantillas de pipeline integradas y sus disparadores (los disparadores por evento y manuales vienen activados; los programados son opcionales, salvo el barrido diario de recolección de basura de worktrees);
- las suites de evaluación iniciales.
Esto ocurre en todos los espacios de trabajo, no solo en el primero. Los agentes sembrados se crean sin adaptador, así que se ejecutan en Control Center (built-in) con el modelo predeterminado de Anthropic (claude-opus-4-8 salvo que fijes otro) hasta que establezcas un adaptador y un modelo para cada agente en Ajustes → Espacio de trabajo → Agentes. Consulta El modelo de agentes.
La escritura de la pertenencia como propietario importa más de lo que parece: sin ella, el espacio de trabajo recién creado no tendría miembros y se denegaría toda llamada con ámbito de espacio de trabajo que hiciera después quien lo creó.
Eliminar, exportar e importar
Sección titulada «Eliminar, exportar e importar»Eliminar un espacio de trabajo marca la fila del registro y desvincula el directorio. El espacio de trabajo desaparece de todas las listas y búsquedas. La fila del registro permanece (con borrado lógico), de modo que el identificador sigue siendo conocido para la copia de seguridad y el mantenimiento, pero workspace.delete elimina de inmediato el directorio de ese espacio de trabajo —base de datos, worktrees, archivos de agentes y lo demás— mediante WorkspaceDatabaseManager.dropAndClose. Solo el propietario del espacio de trabajo puede eliminarlo.
Como un espacio de trabajo es un archivo, pasar un espacio de trabajo de un sitio a otro es una operación de archivo en lugar de un volcado tabla por tabla:
workspace.exportes un únicoVACUUM INTO: una instantánea coherente y desfragmentada tomada dentro de una transacción de lectura mientras el servidor sigue atendiendo.workspace.importadopta un archivo así y sustituye lo que el espacio de trabajo de destino contenga en ese momento. Laworkspace_metaincrustada permite a una importación distinguir «mi propio archivo, readoptado» de «un archivo de otra instalación» (esto último está permitido, pero se registra en lugar de pasar inadvertido).server.backupNowhace una instantánea de toda la instalación en un directorio con marca de tiempo que replica el directorio de datos activo —manifest.json,global.dby un<workspaceId>/workspace.dbpor espacio de trabajo—, así que restaurar es copiarlo de vuelta.server.listBackupsvuelve a leer ese directorio, de la instantánea más reciente a la más antigua, con el tamaño y la lista de espacios de trabajo de cada instantánea. Una instantánea cuyo manifiesto falte o que nombre archivos que no están se sigue notificando, marcada como incompleta: ocultarla es como un operador llega a creer que tiene una copia de seguridad de la que carece.
Las operaciones de copia de seguridad están en Ajustes → Servidor → Copia de seguridad y restauración:
Crear copia ahora hace una instantánea de la instalación, la lista muestra qué instantáneas están
completas y permite al propietario de la instalación eliminar una tras confirmarlo, y cada
espacio de trabajo ofrece exportación e importación. El pipeline integrado Workspace backup
toma solo la base de datos de ese espacio de trabajo con una programación semanal y elimina sus propias
copias de seguridad más antiguas que la antigüedad de retención configurada. Restaurar un espacio de trabajo desde una
instantánea de la instalación es workspace.import apuntando al
<workspaceId>/workspace.db de la instantánea; restaurar una instalación completa sigue siendo una
recopia del directorio de la instantánea con el servidor detenido.
Lo que ninguno de ellos transporta es el resto del directorio del espacio de trabajo. Un espacio de trabajo acumula más que una base de datos —imágenes pegadas, archivos de skills y de agentes, credenciales de chat, worktrees—, y la exportación y la importación mueven el archivo, así que todo lo que está a su lado se queda donde está. Eso es deliberado para las credenciales y prescindible para los worktrees; para el resto es un límite que conviene conocer y no una función. La referencia de copias de seguridad tiene la tabla completa.
Mover una copia de seguridad entre el servidor y tu dispositivo
Sección titulada «Mover una copia de seguridad entre el servidor y tu dispositivo»Todas las operaciones anteriores hablan en rutas del servidor, lo cual es una respuesta completa solo cuando el servidor es tu propia máquina. Tres rutas HTTP firmadas —/backup/workspace, /backup/snapshot y /backup/restore— transportan los bytes para cualquier otra topología, por el mismo carril autenticado que ya usan el proxy de medios y el almacén de imágenes. En la página esto es un botón Descargar junto a cada exportación y cada instantánea (tú eliges dónde acaba) y Elegir un archivo y subirlo para restaurar desde un archivo que esté en la máquina que estás usando. La subida es la que funciona cuando el servidor no es tu máquina: workspace.import necesita que el archivo ya esté en el host, y así es como llega hasta allí.
Merece la pena conocer tres propiedades:
- Una descarga crea una copia nueva y el servidor no conserva nada de ella. Descargar no es «traer el archivo que creó el botón de exportación»: exporta de nuevo, transmite eso y lo elimina. La respuesta es
no-storeconAccept-Ranges: nonepor la misma razón: reanudar un rango empalmaría dos exportaciones distintas en un único archivo que parece válido y no lo es. - Una subida se transmite a disco en streaming y nunca se almacena en búfer, en ambos extremos, y la copia preparada se elimina en todas las salidas posibles, incluido un rechazo. La base de datos de un espacio de trabajo no es una captura de pantalla.
- Una conexión retransmitida no tiene origen HTTP, así que allí los controles de transferencia están deshabilitados con una nota que explica por qué. Todo lo que habla en rutas del lado del servidor sigue funcionando a través del relé; solo los carriles de bytes necesitan una conexión directa.
Varios espacios de trabajo
Sección titulada «Varios espacios de trabajo»Puedes ejecutar varios espacios de trabajo en paralelo. Cada uno funciona de forma independiente: los agentes de un espacio de trabajo no pueden enviar mensajes a los agentes de otro, ni leer la memoria de otro espacio de trabajo, ni ver sus tickets. La resolución de destinatarios para la mensajería entre agentes es exacta y nunca cruza un espacio de trabajo.
No existe ningún panel que cruce espacios de trabajo. La superficie de analítica de /workspaces/:workspaceId/observability se suscribe a un feed global acotado de ejecuciones recientes y lo reduce de inmediato al espacio de trabajo activo, así que lo que ves ahí es un espacio de trabajo a la vez. Las únicas superficies genuinamente de varios espacios de trabajo con las que trata una persona son el selector de espacios de trabajo y el conmutador.
Un límite práctico que conviene conocer: un espacio de trabajo que alguien está usando permanece abierto —no hay LRU. A partir de 32 de ellos, el servidor avisa en lugar de rechazar, porque cada archivo abierto mantiene un isolate en segundo plano y una caché de páginas. La expansión entre espacios de trabajo abre archivos de forma transitoria y los cierra después si ningún otro los ha reclamado.
Conceptos relacionados
Sección titulada «Conceptos relacionados»- Multijugador: pertenencia, roles y concesiones por repositorio — la mitad del aislamiento relativa al acceso
- El modelo de agentes: los agentes pertenecen exactamente a un espacio de trabajo
- Memoria y conocimiento: la memoria tiene ámbito de espacio de trabajo
- Arquitectura: dónde encajan las bases de datos en la separación cliente/servidor
- Hacer copia de seguridad y restaurar: hacer una instantánea, mover un espacio de trabajo, guardar copias en otro sitio
- Copia de seguridad, exportación e importación: cada operación, ruta, campo del manifiesto y límite
- Añadir repos: registrar un checkout en un espacio de trabajo