DeepSeek Harness: Isolamento de Serviço e Escopo

Última atualização: 2026-08-31

Em ambientes multi-Agent, multi-sessão, serviços compartilhados são tanto bênção quanto maldição — serviços globais são convenientes mas propensos a conflitos, serviços isolados são seguros mas comunicação custa mais. O sistema de escopo do Cordis equilibra ambos: compartilhado por padrão, isolado sob demanda.

💡 Dica: O princípio central do escopo é "compartilhado por padrão, isolado sob demanda" — a maioria dos serviços pode ser globalmente compartilhada; apenas serviços que precisam de isolamento requerem configuração isolate. Não-isolamento é a norma; isolamento é a exceção.

📋 Pré-requisitos: Ter completado 19-service.md, entender a classe base Service

1. O Que Você Vai Aprender

Isolamento e Escopo de Serviço


2. Escopo Global

(1) Comportamento Padrão

▶ Exemplo 1: Serviço Global (Singleton)

Por padrão, todos os Services são globais — há apenas uma instância em toda a instância DSH:

TYPESCRIPT
export default class CacheService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'cache')  // Globalmente único
  }
}

(2) Características de Serviços Globais

Característica Descrição
Singleton Apenas uma instância por processo
Compartilhado Todas as sessões e requisições compartilham o mesmo estado
Sem isolamento Dados modificados pela sessão A são visíveis à sessão B

(3) Cenários Aplicáveis

(4) Problema de Vazamento de Dados

TYPESCRIPT
// ❌ Cache global causa vazamento de dados entre sessões
export default class CacheService extends Service {
  private data = new Map<string, any>()
  
  set(key: string, value: any) {
    this.data.set(key, value)
  }
}

// Sessão A: ctx.cache.set('temp', 'secret-data')
// Sessão B: ctx.cache.get('temp') → 'secret-data' (vazou!)

3. Escopo de Sessão

(1) Conceito

▶ Exemplo 2: Serviço com Escopo de Sessão

Escopo de sessão cria uma instância de serviço independente para cada sessão:

TYPESCRIPT
export default class SessionCacheService extends Service {
  static scope = 'session'

  constructor(ctx: Context) {
    super(ctx, 'session-cache')
  }
}

(2) Diagrama de Ciclo de Vida

100%
graph LR
    S1[Sessão A criada] --> C1[Instância CacheService A]
    S2[Sessão B criada] --> C2[Instância CacheService B]
    S1 --> D1[Sessão A destruída → CacheService A destruído]
    S2 --> D2[Sessão B destruída → CacheService B destruído]

(3) Declaração de Escopo

TYPESCRIPT
export default class SessionCacheService extends Service {
  static scope = 'session'
  // Ou
  // static scope = Symbol('session')
}

(4) Cenários Aplicáveis

(5) Efeito de Isolamento Entre Sessões

TEXT 📖 Somente leitura
Sessão A:
  ctx.sessionCache.set('key', 'value-A')

Sessão B:
  ctx.sessionCache.get('key') → undefined  (isolado)

Sessão A:
  ctx.sessionCache.get('key') → 'value-A'  (acessível dentro da sessão)

4. Escopo de Requisição

(1) Conceito

Escopo de requisição cria uma instância independente para cada chamada de ferramenta ou requisição LLM:

TYPESCRIPT
export default class RequestContextService extends Service {
  static scope = 'request'

  constructor(ctx: Context) {
    super(ctx, 'request-context')
  }
}

(2) Ciclo de Vida do Escopo de Requisição

100%
graph LR
    R1[Requisição 1 inicia] --> S1[Instância de serviço 1]
    R2[Requisição 2 inicia] --> S2[Instância de serviço 2]
    R1 --> E1[Requisição 1 completa → instância 1 destruída]
    R2 --> E2[Requisição 2 completa → instância 2 destruída]

(3) Cenários Aplicáveis

(4) Comparação dos Três Níveis de Escopo

Dimensão Global Sessão Requisição
Instâncias 1 1 por sessão 1 por requisição
Ciclo de vida Tempo de vida do processo Tempo de vida da sessão Tempo de vida da requisição
Compartilhamento de estado Globalmente compartilhado Dentro da sessão Apenas dentro da requisição
Memória Baixa Média Alta
Melhor para Config/pools de conexão Cache/histórico de sessão Permissões/timing

5. Configuração isolate Realm

(1) Conceito de Realm

Um realm é o domínio de isolamento do Cordis — criando espaços de plugin independentes dentro da mesma instância DSH:

YAML
# cordis.yml
realms:
  agent-a:
    isolate: ['cache', 'tools']
    plugins:
      my-tool-a:
        $insert: ./plugins/tool-a
  
  agent-b:
    isolate: ['cache', 'tools']
    plugins:
      my-tool-b:
        $insert: ./plugins/tool-b

(2) Campo isolate

A lista isolate especifica quais serviços recebem instâncias independentes dentro do realm:

YAML
realms:
  my-realm:
    isolate:
      - cache       # serviço cache recebe instância independente
      - tools       # serviço tools recebe instância independente
      # Serviços não listados permanecem globalmente compartilhados

(3) Instâncias de Serviço Dentro de um Realm

TEXT 📖 Somente leitura
Global: llm (compartilhado)
realm-a: cache (independente), tools (independente)
realm-b: cache (independente), tools (independente)

Plugins no realm-a → ctx.cache = cache do realm-a
Plugins no realm-b → ctx.cache = cache do realm-b
Eles não afetam uns aos outros

(4) Casos de Uso de Realm

Cenário Descrição
Multi-Agent Diferentes Agents têm diferentes conjuntos de ferramentas e caches
Multi-tenant Serviços de diferentes tenants são mutuamente isolados
Testes Realm de teste não afeta realm de produção
Teste A/B Dois realms usam implementações de serviço diferentes

(5) Comunicação Cross-Realm

▶ Exemplo 3: Comunicação entre Realms via Serviço Global

Realms são isolados por padrão mas podem se comunicar através de serviços globais:

TYPESCRIPT
// Serviço global (não afetado por isolate)
export default class EventBusService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'event-bus')  // Não na lista isolate → globalmente compartilhado
  }

  emit(event: string, data: any) { /* ... */ }
  on(event: string, handler: Function) { /* ... */ }
}

// Plugin no realm-a
ctx.eventBus.emit('data-updated', { source: 'realm-a' })

// Plugin no realm-b
ctx.eventBus.on('data-updated', (data) => {
  ctx.logger.info(`recebido de ${data.source}`)
})

6. Escopo e Presets de Agent

(1) Conceito de Preset de Agent

Um preset de Agent é uma configuração de Agent pré-definida incluindo conjunto de ferramentas, parâmetros de modelo e configurações de escopo:

YAML
presets:
  coder:
    model: deepseek-coder
    tools: [file_edit, shell, search]
    mode: standard
    
  reviewer:
    model: deepseek-chat
    tools: [file_edit, search]
    mode: minimal
    isolate: [cache]

(2) Relação Preset e Escopo

Cada preset pode especificar uma lista isolate, criando instâncias de serviço isoladas para aquele Agent:

TEXT 📖 Somente leitura
coder Agent:  cache compartilhado, tools independente
reviewer Agent: cache independente, tools compartilhado

(3) Cenário Multi-Agent

YAML
# cordis.yml
agents:
  coder:
    preset: coder
    isolate: [tools]
    
  reviewer:
    preset: reviewer
    isolate: [tools, cache]

(4) Colaboração Inter-Agent

100%
graph TB
    subgraph Global
        LLM[llm Service]
        EVENT[event-bus Service]
    end
    subgraph Agent-Coder
        CT[tools Service]
        CC[cache Service]
    end
    subgraph Agent-Reviewer
        RT[tools Service]
        RC[cache Service]
    end
    CT --> LLM
    RT --> LLM
    CT --> EVENT
    RT --> EVENT

7. Isolamento de Serviço Multi-Agent

(1) Seleção de Estratégia de Isolamento

TEXT 📖 Somente leitura
Totalmente compartilhado:     Todos os serviços globais → simples mas potencial de conflitos
Totalmente isolado:   Todos os serviços independentes → seguro mas desperdício de recursos
Isolamento misto:  Serviços centrais compartilhados + serviços de negócio isolados → abordagem equilibrada

Isolamento misto recomendado:

Tipo de Serviço Estratégia de Isolamento Motivo
llm Compartilhado Chamadas de API podem ser reutilizadas
sessions Compartilhado Gerenciamento unificado de sessões
tools Isolado Cada Agent tem conjunto diferente de ferramentas
cache Isolado Cada Agent tem cache independente
fs Compartilhado Apenas um sistema de arquivos

(2) Exemplo de Configuração Multi-Agent

YAML
agents:
  frontend-dev:
    preset: coder
    isolate: [tools, cache]
    tools:
      - file_edit
      - shell
      - search
    config:
      cache:
        maxSize: 100
  
  backend-dev:
    preset: coder
    isolate: [tools, cache]
    tools:
      - file_edit
      - shell
      - search
      - database
    config:
      cache:
        maxSize: 200

(3) Estimativa de Consumo de Recursos

Nível de Isolamento Memória CPU Conexões
Compartilhado global 1x 1x 1x
2-Agent isolado ~2x ~1.5x ~2x
5-Agent isolado ~5x ~3x ~5x

(4) Detecção de Vazamento de Isolamento

TYPESCRIPT
// Monitorar contagens de instância de serviço
ctx.on('service/created', (name, instance) => {
  ctx.logger.info(`serviço criado: ${name}, instâncias totais: ${countInstances(name)}`)
})

// Se a contagem de instâncias de um serviço excede em muito a contagem de Agents, pode haver vazamento

❓ Perguntas Frequentes

P Sem declarar scope, um serviço é global por padrão?
R Sim. Um Service sem static scope é um singleton global por padrão.
P Services com escopo de sessão são limpos quando uma sessão termina?
R Sim. Quando uma sessão é destruída, suas instâncias de Service são automaticamente limpas, incluindo recursos registrados via ctx.effect.
P A lista isolate de um realm pode ser modificada dinamicamente?
R Não. Configuração de realm é determinada na inicialização; modificações requerem reinicialização.
P Um Service pode existir em múltiplos escopos simultaneamente?
R Não. Um Service é global, em nível de sessão, ou em nível de requisição. Se precisar de compartilhamento de dados cross-escopo, use um event bus global.
P A sobrecarga de desempenho do escopo de requisição é significativa?
R Criar e destruir Services por requisição tem custo. Use escopo de requisição apenas quando realmente necessário; caso contrário use global ou sessão.
P Como depurar problemas de escopo?
R Imprima o ID da instância no construtor do Service: typescript constructor(ctx: Context) { super(ctx, 'cache') console.log(`instância cache criada: ${this.id}, escopo: ${this.scope}`) }

📖 Resumo


📝 Exercícios

1. ⭐ Básico: Escreva um SessionStateService com escopo de sessão que mantém armazenamento chave-valor independente por sessão. Inicie duas sessões e verifique isolamento de dados.

2. ⭐⭐ Intermediário: Configure um realm que isola serviços de cache e tools. Acesse cache dentro e fora do realm, verificando que recebe instâncias diferentes.

3. ⭐⭐⭐ Desafio: Projete um sistema dual-Agent: coder e reviewer. Coder tem ferramentas file_edit/shell, reviewer apenas file_edit/search. Ambos compartilham llm e sessions, mas cache e conjunto de ferramentas são independentemente isolados. Verifique: a ferramenta shell do coder é invisível para o reviewer, e seus caches não afetam uns aos outros.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%