Skip to content

Built-in profiles

A profile is a reusable partial spec. The core ships six: defaults, which is always the first layer of every spec, and five starting points for common kinds of app, which a spec selects with extends: ["profile://<name>"]. Built-in profiles are merged before org profiles, so an org baseline can tighten them (Layers). Their guards run in the platform band.

Change a profile's guard by restating its id in your spec ({ id: rag-injection, threshold: 0.7 }), switch it off with enabled: false, or add your own guards after it. None of the built-in profiles lock anything.

Profile For Adds
defaults Every spec Safe, minimal settings: no telemetry export, no content capture, manifests required, one repair, cel_lite policy, in-memory approvals and state
extraction Typed extraction PII redaction on input, secrets check on output, one repair then escalate, a 1 minute deadline
rag Retrieval-augmented answers PII redaction and injection checks on input, injection check on retrieved context, secrets check on output, a 30 second deadline
agent Tool-using agents Injection check on input, secrets redacted from tool results, secrets check on output, manifests required, 20 tool calls, a 2 minute deadline
workflow Deterministic pipelines Secrets check on output, a 5 minute deadline
chat Conversational apps PII redaction on input, secrets check on each streamed chunk and on output, a 1 minute deadline

defaults

apiVersion: harnessweaver/v1
kind: Profile
metadata: { name: defaults, version: 1.0.0, owner: harnessweaver }
observability:
  exporter: none
  capture_content: false   # R9: no raw content in telemetry
  configure_sdk: false     # R5: the app owns its OpenTelemetry setup
tools:
  require_manifest: true   # S2: no tool runs without a manifest
  max_output_bytes: 20000
validation:
  max_repairs: 1
  on_failure: block
policy:
  use: cel_lite
  default_effect: allow
approvals:
  use: memory
  timeout: 24h
  on_timeout: escalate
state:
  use: memory
require_level:
  default: L0

extraction

metadata: { name: extraction, version: 1.0.0, owner: harnessweaver }
guardrails:
  input:
    - { id: extraction-pii, use: pii.regex, action: redact }
  output:
    - { id: extraction-secrets, use: secrets.scan, action: block }
validation:
  max_repairs: 1
  on_failure: escalate
budgets:
  per_run: { deadline: 1m }

Used by Example 01 and the extraction template.

rag

metadata: { name: rag, version: 1.0.0, owner: harnessweaver }
guardrails:
  input:
    - { id: rag-pii, use: pii.regex, action: redact }
    - { id: rag-injection, use: injection.heuristic, action: block }
  context:
    - { id: rag-context-injection, use: injection.heuristic, action: block }
  output:
    - { id: rag-secrets, use: secrets.scan, action: block }
budgets:
  per_run: { deadline: 30s }

At the context stage a block drops the item, so a poisoned document never reaches the model while the rest of the answer goes ahead. Used by Example 02 and the rag template.

agent

metadata: { name: agent, version: 1.0.0, owner: harnessweaver }
guardrails:
  input:
    - { id: agent-injection, use: injection.heuristic, action: block }
  tool_result:
    - { id: agent-tool-secrets, use: secrets.scan, action: redact }
  output:
    - { id: agent-secrets, use: secrets.scan, action: block }
tools:
  require_manifest: true
budgets:
  per_run: { max_tool_calls: 20, deadline: 2m }

Used by Example 03 and the agent template.

workflow

metadata: { name: workflow, version: 1.0.0, owner: harnessweaver }
guardrails:
  output:
    - { id: workflow-secrets, use: secrets.scan, action: block }
budgets:
  per_run: { deadline: 5m }

Used by the workflow template.

chat

metadata: { name: chat, version: 1.0.0, owner: harnessweaver }
guardrails:
  input:
    - { id: chat-pii, use: pii.regex, action: redact }
  stream:
    - { id: chat-stream-secrets, use: secrets.scan, action: block }
  output:
    - { id: chat-secrets, use: secrets.scan, action: block }
budgets:
  per_run: { deadline: 1m }

The stream guard checks each chunk as it is produced, so a secret is cut before the rest of the answer streams. Used by the chat template.

Org and plugin profiles

Your platform team's profiles work the same way, with three additions only profiles can make: locks, bounds and require_level. See Writing an org baseline. A plugin can ship profiles too (hw.Plugin(profiles={"baseline": "profiles/baseline.yaml"})), which specs select as profile://<namespace>.<name>@<range>; they count as org layers.