skills/<name>/skill.json. Each manifest declares what the skill does, what it needs, and its security classification.
Schema reference
Field details
name
Unique identifier for the skill. Must match the directory name under skills/. Convention: lowercase kebab-case.
action_risk
Required. The minimum autonomy score required to invoke this skill without explicit CEO approval. Curia will not start if any skill omits this field.
| Label | Minimum score | Use for |
|---|---|---|
none | 0 | Read-only operations with no side effects — web search, reading email, summarizing |
low | 60 | Internal state writes — memory, contacts, configuration |
medium | 70 | Outbound communications — sending email, Signal messages |
high | 80 | Calendar writes, commitments on behalf of the CEO |
critical | 90 | Financial, destructive, or irreversible operations |
75 for a skill that should unlock just above “approval required” but below “spot-check”). Numbers outside [0, 100] produce a validation error at load time.
sensitivity
| Value | Meaning |
|---|---|
normal | Can be auto-approved based on autonomy score |
elevated | Requires human approval on first use, regardless of autonomy score |
inputs and outputs
Shorthand type declarations for skill parameters and return values. Field names map to type strings:
| Type string | Meaning |
|---|---|
"string" | Required string |
"string?" | Optional string |
"number" | Required number |
"boolean" | Required boolean |
"object" | Required object (any shape) |
tools/list response is used directly instead of this shorthand.
permissions
Array of permission names this skill requires. Validated at load time.
secrets
Array of vault secret keys this skill needs access to via ctx.secret(). Secrets are resolved from the encrypted vault (with an env-var fallback applied at bootstrap). Only secrets declared here are accessible — the skill cannot read arbitrary secrets or environment variables. Keys are lowercase snake_case (e.g. tavily_api_key, nylas_api_key).
This is the runtime allowlist — what the handler may read while executing. To require that a secret be present before the skill can be installed or enabled, declare it in install.requires_secrets instead (a skill commonly declares the same key in both).
timeout
Per-invocation timeout in milliseconds. Default: 30000 (30 seconds).
capabilities
Declares which privileged services this skill needs from the execution layer. Only known capability names are accepted — the loader validates against a fixed allowlist at startup and rejects unknown names.
| Capability | Service provided |
|---|---|
bus | Event bus access |
agentRegistry | Agent registry for delegation |
outboundGateway | Outbound message delivery (email, Signal) |
heldMessages | Held message service |
schedulerService | Job scheduling |
entityMemory | Knowledge graph read/write |
nylasCalendarClient | Calendar operations via Nylas |
autonomyService | Autonomy score management |
executiveProfileService | CEO writing voice profile |
officeIdentityService | Office identity — assistant name/title, tone, decision posture, and behavioral preferences. Used by behavioral-preferences-update. |
browserService | Playwright browser for web interaction |
bullpenService | Inter-agent discussion threads |
skillSearch | Search the skill registry |
actionLogRepo | Autonomy action log for approval lifecycle management |
executionLayer | Re-invoke skills with humanApproved bypass (CEO-only, approve-action skill) |
confidencePipeline | Contact confidence scoring — fire signals when modifying trust-related data |
tempFileStore | Write binary buffers to tmpfs; returns file:// URLs for MCP tool handoff |
infraLlm | Constrained LLM access — classify() and extract() only, no raw chat() |
outboundContext | Register/release outbound-context entries for delegation-aware reply correlation. Pre-scoped to the current conversation. |
contactService, entityContextAssembler, agentPersona) are universal — available to every skill without declaration.
allowed_callers
Optional. Restricts which agents may invoke this skill. When set, only the named agents can call the skill — all others are rejected with a structured failure before any other gate (autonomy, elevation) is evaluated.
- Agent names are validated against the loaded agent registry at startup — unknown names cause a hard startup failure.
- CEO-approved re-executions bypass the caller gate.
- The special value
"system"matches system-layer invocations (checkpoint processor, etc.). - Omit the field entirely (or set to
[]) to allow any agent — this is the default.
context_bridge (input field)
Optional input on send skills (email-send, email-reply, signal-send). A JSON-encoded object that lets the caller attach delegation metadata to the outbound-context entry that’s auto-registered when the message ships.
| Field | Purpose |
|---|---|
agent_id | Originating specialist (coordinator, research-analyst, meeting-debrief, …) |
expected_reply | Short hint about the kind of reply being awaited |
delegation_hint | Free-form instruction the dispatcher surfaces back on inbound replies (e.g. “reply belongs to research-analyst”) |
metadata | Optional JSON object — structured delegation context (e.g. resume_token for multi-turn clarification) |
expires_in_hours | Overrides the global contextBridge.explicitExpiryHours for this entry |
context_bridge is passed. The optional field is for callers (specialists, the coordinator) that want richer delegation context.
entity_enrichment
Optional. When declared, the execution layer automatically assembles entity context before invoking the skill handler, injecting it into ctx.entityContext.
| Field | Description |
|---|---|
param | The input key containing contact/entity IDs to enrich |
default | What to use when the input is not provided: "caller" (the message sender) or "agent" (the agent’s own contact) |
install
Optional. Declares install-time requirements that the registry enforces before a skill can be installed or enabled. Skills live in a DB-backed registry and only enabled skills are loaded at startup.
| Field | Description |
|---|---|
requires_secrets | Array of vault secret keys that must already exist in the vault before the skill can be installed or enabled. The registry rejects the install/enable until every listed key is present. |
secrets allowlist: secrets controls what the handler may read while executing; install.requires_secrets is a precondition gate checked at install/enable time. The web-search skill is the canonical example — it declares tavily_api_key here so it cannot be enabled until you have provisioned a Tavily key.
Example
Built-in skills
Catalog of all skills Curia ships with.
Autonomy engine
How action_risk connects to the autonomy score.