Skip to content

Disclose that an agent is an AI

Declare requires_ai_disclosure in an agent’s PromptPack so the facade tells each client it is talking to an AI, and so the session record shows that it did.

  • A PromptPack you can republish as a new version (published PromptPacks are immutable).
  • An agent that serves clients over the WebSocket facade.
  • session-api with a Postgres warm store, to keep the delivery record.
  • Enterprise with privacy-api, to count missed disclosures.
  1. Set metadata.governance.requires_ai_disclosure in the pack (promptpack-spec RFC 0013):

    {
    "id": "customer-support",
    "metadata": {
    "governance": {
    "requires_ai_disclosure": true,
    "intended_purpose": "Answer billing questions for retail customers",
    "accountable_owner": "support-platform@example.com"
    }
    }
    }
    ValueMeaning
    trueA human counterparty must be told this is an AI.
    falseThe author considered disclosure and declared none is due, for example a backend agent with no human on the other end.
    omittedThe author declared nothing.
  2. Publish the pack as a new PromptPack version and point the agent at it. The facade reads the declaration once, at startup.

See PromptPack for the other governance fields.

On connect, the WebSocket facade puts the declaration on the connected frame, before the user has said anything. The same frame carries it when a client resumes a parked session (resumed is then true). A pack that declares nothing sends no ai_disclosure field.

The following frame is illustrative:

{
"type": "connected",
"session_id": "3f1c…",
"connected": { "capabilities": {}, "ai_disclosure": true }
}

The dashboard console shows a “You are talking to an AI” alert above the transcript when the value is true.

A client you build yourself must render the notice. It can then send {"type": "disclosure_ack"}; the facade records that as the client-asserted event ai.disclosure.displayed. See the WebSocket protocol reference.

  1. Open a new session with the agent.

  2. Forward the group’s session-api Service, mint a token and read the session. The Service is session-<workspace>-<group> in the workspace namespace. The token needs the audience omnia-session-api.

    Terminal window
    kubectl port-forward -n <workspace-namespace> svc/session-<workspace>-<group> 8080:8080
    export SA_TOKEN=$(kubectl create token default -n <workspace-namespace> --audience omnia-session-api)
    curl -sS "http://localhost:8080/api/v1/sessions/<session-id>" \
    -H "Authorization: Bearer $SA_TOKEN"

    The response nests the record under session. The following output is illustrative:

    {
    "session": {
    "aiDisclosure": {
    "declared": true,
    "delivered": true,
    "deliveredAt": "2026-09-03T12:00:00Z",
    "facadeType": "websocket"
    }
    }
    }

    deliveredAt is absent when delivered is false, and declared is absent when the pack declared nothing.

  3. Open the session in the dashboard. The session detail page shows one of these verdicts:

    VerdictMeaning
    Disclosure sentDeclared true and sent.
    Required, none sentDeclared true and not sent.
    No disclosure requiredDeclared false.
    Pack declared nothingOmitted.
    Not recordedThe writer reported no posture.

If you wrote your own facade with the pkg/facade SDK, it must honour the declaration.

import sdkfacade "github.com/altairalabs/omnia/pkg/facade"
// Once, at startup.
declared := sdkfacade.LoadDisclosure(packPath, log)
// Per session, after the disclosure is written to your transport.
d := sdkfacade.Disclosure{
Declared: declared,
Delivered: sent,
DeliveredAt: sentAt,
FacadeType: "my-facade",
}
d.LogViolation(log, sessionID) // no-op unless declared and not delivered
  1. Set Delivered only after the write succeeds. A frame that failed to send disclosed nothing.
  2. Include the same four fields as aiDisclosure in the body of POST /api/v1/sessions when you create the session. session-api stores them at creation.
  3. Call d.RecordSent to add the ai.disclosure.sent event to the session trace.

A pack with requires_ai_disclosure: true whose session shows no delivery is a detectable violation. Two places report it.

session-api writes an ai_disclosure_missing event to its audit_log when it creates the session. The event drains to the privacy-api audit hub, keyed by Workspace UID. A delivered disclosure emits no event.

  1. Forward the workspace’s privacy-api Service, privacy-<workspace>, using the token from the Verify step:

    Terminal window
    kubectl port-forward -n <workspace-namespace> svc/privacy-<workspace> 8087:8080
  2. Read the running count, passing the Workspace UID as workspace:

    Terminal window
    curl -sS "http://localhost:8087/api/v1/privacy/enforcement-stats?workspace=<workspace-uid>" \
    -H "Authorization: Bearer $SA_TOKEN"

    The count is aiDisclosureMissing, next to piiBlocked, redactions and policyDenied.

The facade also logs at default verbosity, so a deployment without session-api still gets a line. The following line is illustrative:

ai disclosure not delivered reason="pack requires disclosure, facade delivered none" declared=true facadeType=custom sessionID=3f1c…

The alert appears only when connected.ai_disclosure is true. A false or omitted value renders nothing. Check that the pack you published sets the field to true.