Competency Authoring

What you'll accomplish: Create a custom competency package with a COMPETENCY.md payload, system prompt, and test it locally.

Package structure

my-competency/
├── MANIFEST.toml          # Package identity (name, title, version, type)
├── README.md              # Human documentation
└── payload/
    └── COMPETENCY.md      # YAML frontmatter + system prompt body

A competency payload is a single COMPETENCY.md file — YAML frontmatter carries structured metadata, and the markdown body IS the system prompt. Identity (name) lives in the sibling MANIFEST.toml, not in COMPETENCY.md frontmatter.

Minimal example

MANIFEST.toml:

[package]
type = "competency"
name = "policy-lookup"
title = "Policy Lookup"
version = "0.1.0"
description = "Retrieves and summarizes insurance policy details"
license = "Apache-2.0"
min_platform_version = "0.5.0"

payload/COMPETENCY.md:

---
description: "Retrieves and summarizes insurance policy details"
skills:
  - claims-core-lookup
---
You are a policy lookup specialist. When asked about a policy:
1. Query the database for the policy by number or customer name
2. Summarize coverage, limits, deductibles, and renewal date
3. Flag any gaps in coverage

Full example

payload/COMPETENCY.md (see MANIFEST.toml schema for the sibling manifest):

---
description: "First Notice of Loss processing for property and auto claims"
skills:
  - document-ocr
  - claims-core-lookup
  - email-skill
schedule: "0 */6 * * *"
schedule_action: "Check for new loss reports and process any unhandled intake items."
integrations:
  - guidewire-claimcenter
  - lexisnexis-clue
inputs:
  - name: loss_description
    type: string
    required: true
  - name: severity
    type: integer
    range: [1, 5]
outputs:
  - name: claim_number
    type: string
  - name: coverage_confirmed
    type: boolean
settings:
  - key: auto_escalate_threshold
    label: Auto-Escalate Severity
    description: "Claims at or above this severity auto-escalate to supervisor"
    type: Select
    default: "4"
    values:
      - "3"
      - "4"
      - "5"
---
You are a claims intake specialist for an insurance company.

Your responsibilities:
1. Collect loss details (date, location, description, parties involved)
2. Verify policy coverage for the reported loss type
3. Create a claim record in ClaimCenter
4. Run a CLUE report for prior claims history
5. Assign initial severity and route to appropriate adjuster queue

Guidelines:
- Always verify the policyholder's identity before proceeding
- Document all collected information in the claim record
- For severity 4-5 claims, escalate immediately to a supervisor queue
- Never approve or deny coverage — only intake and route

COMPETENCY.md field reference

Frontmatter field ordering

Fields should follow this ordering convention:

  1. Identitydescription
  2. Dependenciesskills, tools, contracts, integrations
  3. Operationalschedule, schedule_action
  4. Data contractinputs, outputs
  5. Configurationsettings

There is no category or permissions field on COMPETENCY.md frontmatter — the struct is deny_unknown_fields, so either would cause the manifest to fail to parse. Categorization happens via MANIFEST.toml's [package.metadata] categories; tool access is scoped on the agent side via AGENT.md's allow_skill_tools/allow_integration_tools (ADR-052), not declared by the competency itself.

Frontmatter fields

FieldTypeRequiredDescription
descriptionstringYesWhat this competency does
skillsstring[]NoSkill packages this competency depends on (kebab-case)
toolsstring[]NoIndividual tool names this competency depends on
contractsstring[]NoIntegration contract names this competency depends on (ADR-051)
integrationsstring[]NoIntegration packages this competency depends on
inputsarrayNoData contract — what the competency expects (see below)
outputsarrayNoData contract — what the competency produces (see below)
settingsarrayNoOperator-configurable settings (see below)
schedulestringNoCron expression
schedule_actionstringNoMessage sent when cron fires (required if schedule is set)

Package identity (name) is not a frontmatter field for any package type — it lives solely in the sibling MANIFEST.toml's [package] name. Classification/discovery tags live in MANIFEST.toml's [package.metadata] categories, not in COMPETENCY.md. The frontmatter struct is deny_unknown_fields: an id/name/category/permissions key (or any other field not listed above) causes the manifest to fail to parse.

Markdown body (system prompt)

The markdown body after the closing --- IS the system prompt. It is injected verbatim into the agent's context when the competency is equipped. Must be non-empty.

inputs / outputs (optional)

Define the data contract — what the competency expects to receive and what it produces.

FieldTypeRequiredDescription
namestringYesParameter identifier
typestringYesData type (string, integer, boolean, etc.)
requiredbooleanNoWhether the input is mandatory
rangearrayNoValid value range (for numeric types)

settings (optional)

FieldTypeRequiredDescription
keystringYesSetting identifier
labelstringNoHuman-readable label
descriptionstringNoWhat this controls
typeenumYesSelect, Text, Toggle, or Number
defaultstringYesDefault value
valuesstring[]NoFor Select: list of valid option values

Tool access is scoped on the agent, not the competency

A competency does not declare permissions or a trust/access policy — there's no such field on COMPETENCY.md. Two separate, agent-side mechanisms control what a competency's declared skills/tools/integrations can actually do once attached:

  • Tool visibility (ADR-052). The agent's AGENT.md frontmatter carries allow_skill_tools/allow_integration_tools — an allowlist of tool names the agent is permitted to invoke, regardless of which competencies expose them. A competency can declare a dependency on a skill/integration; if the agent's allowlist doesn't include its tools, the agent still can't call them.
  • PII policy. What data a tool call is allowed to see or emit is governed entirely by the operator-owned carrier-pii-policy.toml (ADR-049) — not by anything the competency or agent declares.

See Using competencies and RBAC for the full access-control picture.

System prompt best practices

Do

  • Be specific about the domain and task boundaries
  • Include explicit safety rails ("Never approve or deny coverage")
  • Reference tools/skills available ("Use the postgresql.query tool to...")
  • Define escalation criteria clearly
  • Keep under 2000 tokens

Don't

  • Include credentials or connection strings
  • Repeat what tools already enforce (permission checks, PII filtering)
  • Include instructions that conflict with platform safety
  • Assume you're the only competency — write prompts that compose well

Multi-competency considerations

Since agents can equip multiple competencies, system prompts are concatenated in position order. Keep these guidelines in mind:

  • Avoid contradictory instructions (e.g., "Always respond in JSON" in one competency vs. prose in another)
  • Don't redefine the agent's identity — describe the role, not "you are the only thing this agent does"
  • Use clear section headers in your prompt so operators can identify which competency contributed what

Testing locally

# 1. Lint the package
hoziron-cli package lint ./my-competency/

# 2. Install the competency definition
hoziron-cli competency install ./my-competency/payload/

# 3. Check skill dependencies
hoziron-cli competency check-deps claims-intake

There is no runtime equip command (see Using competencies — competency attachment is definition-driven). To actually exercise the competency against an agent, add it to a test agent-template's AGENT.md:

---
description: "Test harness for my-competency"
competencies:
  - claims-intake
---

Then install (or reinstall, if iterating) the agent package and message it:

hoziron-cli package build ./my-test-agent/
hoziron-cli catalog install my-test-agent --activate
hoziron-cli agent list   # find the new agent's ID
hoziron-cli agent chat <agent-id>
# Test: process a new auto claim for policy #POL-2024-100

Adjust settings on that agent's binding via the agent-scoped config endpoint:

curl -X PUT http://localhost:4200/agents/{agent-id}/competencies/claims-intake/config \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer hzk_..." \
  -d '{"auto_escalate_threshold": "3"}'

Next steps


Related: