# Record types

Schemas for the new record types the system needs to host external resources, tools, activation policies, runs, artifacts, and memory. Written against the polymorphic `records` substrate that has since been replaced by per-entity tables — landing them today means **new tables**, not new `type` discriminants. Read as design intent for the shapes themselves.

```
resource           parent: house     {kind: discord-channel|github-repo|sandbox|durable-stream|...,
                                      external_id, config}                — open enum on kind
tool               parent: house|null {name, kind: builtin|mcp|http, schema?, config?}
                                      null parent = global platform capability
activation-policy  parent: agent     {trigger: cron|interval|webhook|stream-event|github-event
                                              |mention|ambient,
                                      config, resource_ids?, tool_ids?, enabled}
                                      replaces trigger_mode + ambient_delay_ms on AgentContent
run                parent: house     {status: queued|dispatching|running|waiting|completed|failed|aborted,
                                      task_ref?, agent_id, sandbox_ref?, session_id?, activation_id?,
                                      started_at?, finished_at?, failure_phase?}
artifact           parent: house     {kind: message|file|url|commit|screenshot|log-ref|...,
                                      label?, external_id?, mime_type?, byte_ref?,
                                      source_run_id?, source_session_id?, resource_id?, metadata?}
memory             parent: agent|house {kind: fact|preference|commitment|reference,
                                        text, confidence?, source_ref?, supersedes?, tags?}
```

Resources are scoped to houses (the right permission boundary — a house admin controls which external targets are available). They do **not** carry secret references — many resources may share one credential, one resource may need several; credential binding is a separate concern. Tools are records with `x` permission gating invocation; global tools are platform capabilities, house-scoped tools are integrations specific to that house. Activation policies own their agent (parent: `agent_id`) — `resource_ids` / `tool_ids` say what the policy cares about; the runtime still permission-checks the agent against those tools and resources before executing.

Run records are created in the substrate when work crosses a shared boundary (remote dispatch, external resource, multi-agent); local-only repo work stays in SQLite. Artifacts live under a durable scope (house/project) because they outlive the runs and sessions that produced them — provenance goes in `content` where it can be queried without polluting the ownership tree. Memory: agent-level memories are private to that agent; house-level memories are shared knowledge within the house. The permission model handles both via parent_id chain-walking.

`Room` extends with optional `kind: 'conversation'|'session'`, `status: 'active'|'idle'|'blocked'|'errored'|'completed'`, `sandbox_ref`, `started_at`, `last_activity_at`. A query for active sessions becomes `where type='room' and content->>'kind'='session' and content->>'status' in ('active','idle','blocked')`.

**Secrets are explicitly not a record type.** They live in a dedicated `secrets` table backed by Supabase Vault — see [system/secrets](../system/secrets.md). The earlier `secret-binding` record type with a `vault_key` indirection was designed before Vault was in scope.

`@arbe/core` changes when these land: add the schemas + content schemas + mutation builders (`createResource`, `createTool`, `createActivationPolicy`, `createArtifact`, `createRun`, `createMemory`); extend `RoomContentSchema`; add runtime helpers `resolveCapabilities(agentId, db)`, `resolveActivationPolicies(agentId, db)`, `resolveSecrets(agentId, resourceIds, db)`; remove `trigger_mode` + `ambient_delay_ms` from `AgentContentSchema` — they move to activation-policy records. The mutation executor already handles arbitrary record types — new types mostly need content validation, not new executor logic.

**Open:** full JSON Schema vs lighter shape for tool input schemas (heavyweight but future-proof — start light); should constraint records exist from day one, or run "capability = tool permission ∩ resource permission" until it breaks (start without; add when a real use case demands narrowing).

**See:** [thinking/capabilities](./capabilities.md), [thinking/activation](./activation.md), [thinking/memory](./memory.md), [thinking/sequencing](./sequencing.md).
