Skip to content
This repository was archived by the owner on Feb 27, 2026. It is now read-only.
This repository was archived by the owner on Feb 27, 2026. It is now read-only.

refactor: Unify agent_turn_context and agent_bootstrap_context schema #158

Description

@NOVA-Openclaw

Background

The two context tables (agent_turn_context and agent_bootstrap_context) evolved separately and have inconsistent column naming and constraints. This creates confusion and maintenance overhead.

Current state

agent_turn_context:

  • context_type (UNIVERSAL/GLOBAL/DOMAIN/AGENT)
  • context_key — scope identifier (domain name, agent name, or *)
  • document_name — redundant with context_key since there's only one row per scope
  • Unique: (context_type, document_name)

agent_bootstrap_context:

  • context_type (UNIVERSAL/GLOBAL/DOMAIN/AGENT)
  • domain_name — set for DOMAIN type
  • agent_name — set for AGENT type
  • document_name — distinguishes multiple documents within a scope
  • Unique: (context_type, COALESCE(agent_name, ''), COALESCE(domain_name, ''), document_name)

Problems

  1. context_key vs domain_name/agent_name — same concept, different names
  2. document_name is redundant in turn context (one row per scope)
  3. No enforcement that UNIVERSAL and GLOBAL have only one row each
  4. COALESCE in unique index is ugly — separate columns for the same logical field

Changes

1. agent_turn_context

  • Drop document_name column
  • Rename context_keycontext_name
  • New unique constraint: (context_type, context_name)
  • context_name values: '*' for UNIVERSAL/GLOBAL, domain name for DOMAIN, agent name for AGENT

2. agent_bootstrap_context

  • Drop domain_name and agent_name columns
  • Add context_name column (replaces both)
  • Keep document_name (bootstrap has multiple documents per scope)
  • New unique constraint: (context_type, context_name, document_name)
  • context_name values: '*' for UNIVERSAL/GLOBAL, domain name for DOMAIN, agent name for AGENT

3. Shared pattern

Both tables use context_type + context_name as the scope identifier. Bootstrap adds document_name as a third dimension for multiple documents per scope.

4. Enforce UNIVERSAL/GLOBAL uniqueness

  • agent_turn_context: Add partial unique index — only ONE row where context_type = 'UNIVERSAL', only ONE row where context_type = 'GLOBAL'
  • agent_bootstrap_context: UNIVERSAL/GLOBAL can have multiple rows (multiple documents), but all share context_name = '*'. Uniqueness is already handled by (context_type, context_name, document_name)

5. Update dependent code

  • get_agent_turn_context() function — query uses context_name instead of context_key
  • get_agent_bootstrap() function — query uses context_name instead of domain_name/agent_name
  • protect_bootstrap_context_writes() trigger — references column names
  • agent-turn-context hook (handler.ts) — if it references column names
  • db-bootstrap-context hook (handler.ts) — column name references
  • Logical replication publications (graybeard_sync_pub) — WHERE clauses reference column names
  • Any CHECK constraints referencing old column names

Migration strategy

  • Pre-migration script to populate context_name from existing domain_name/agent_name/context_key
  • Then pgschema handles the structural diff
  • Backward-compatible: existing data preserved, just column renames

Constraints

  • One UNIVERSAL row in agent_turn_context, one GLOBAL row
  • One DOMAIN row per domain name in agent_turn_context
  • One AGENT row per agent name in agent_turn_context
  • Bootstrap allows multiple rows per scope (distinguished by document_name)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions