SocialHub.AI
New · rolling out per workspace

AI Governance: Introspection & Approvals

Flash puts every AI-initiated action behind a per-action authorization gear auto, review or forbidden— configured per workspace in the AI Activity & Approvals console. For an AI client over MCP this means two things: you can discoverthe business objects and the actions you're allowed to take before acting, and your write calls return structured results — executed, pending human approval, or refused with a machine-readable reason.

This guide covers the introspection tools, the write semantics under a review gear, and the approval lifecycle. It builds on the same governed MCP server documented in the MCP Integration guide. For the business overview, see the AI Governance & Approvals product page. Gear routing is enabled progressively — the behavior below applies as governed actions roll out to your workspace.

Business-object introspection (scope introspection:read)

Three read tools let an AI client learn the shape of the business before touching it: which objects exist (including the workspace's own custom fields and custom objects), what each attribute means, how objects relate, and which actions are executable — with their preconditions and current gear. A well-behaved agent calls these first and only proposes actions the gears actually allow.

list_objectsread

Discover the business objects available to the key's workspace: member, order, coupon, campaign, store, product, segment, tag — plus any custom objects the workspace has defined. Returns each object's key, label and a one-line meaning. Call first to learn what exists before reading or acting.

Parameters: (none)
describe_objectread

One object's full shape: its attributes (including the workspace's custom fields) with their type and business meaning, and its relationships to other objects (e.g. an order belongs to a member; a coupon can be issued to a member). PII fields are returned as metadata only — name, type, semantics and a pii flag — never their values.

Parameters: object
list_actionsread

The actions an AI client may take, with each action's preconditions and its current authorization gear (auto / review / forbidden) as configured by the workspace. Filter by object to see only the actions that touch it. What this returns is exactly what the governance layer will enforce — use it to avoid proposing actions that will be refused.

Parameters: object?

PII is metadata-only, by design. Introspection describes fields that hold personal information (their name, type, meaning and a pii flag) but never returns their values. Reading actual member data goes through the member read tools and their own scopes.

Example: describe an object, then check the gears

Descriptive examples of the request/response shape (abbreviated — real responses list every field and action):

// describe_object { "object": "member" }
{
  "object": "member",
  "label": "Member",
  "meaning": "A loyalty program member owned by this workspace.",
  "fields": [
    { "name": "email",            "type": "string",  "pii": true,
      "meaning": "Contact email. PII: metadata only — values are never returned here." },
    { "name": "tier",             "type": "string",  "pii": false,
      "meaning": "Current loyalty tier." },
    { "name": "membership_no",    "type": "string",  "pii": false, "custom": true,
      "meaning": "Workspace-defined custom field." }
  ],
  "relationships": [
    { "to": "order",  "kind": "has_many",  "meaning": "Orders placed by this member." },
    { "to": "coupon", "kind": "has_many",  "meaning": "Coupons issued to this member." },
    { "to": "tag",    "kind": "has_many",  "meaning": "Tags currently applied to this member." }
  ]
}
// list_actions { "object": "member" }
{
  "actions": [
    { "action": "issue_coupon",     "gear": "review",
      "preconditions": ["member has consent", "coupon pool has stock"] },
    { "action": "earn_points",      "gear": "auto",
      "preconditions": ["amount within the workspace cap"] },
    { "action": "assign_tag",       "gear": "auto",
      "preconditions": ["tag exists and is active"] },
    { "action": "add_member_note",  "gear": "auto",
      "preconditions": ["note passes server-side sanitation"] },
    { "action": "send_campaign",    "gear": "review", "locked": true,
      "preconditions": ["sending can never be auto — a human always approves"] }
  ]
}

The gear you see is the gear that will be enforced — the workspace configures it per action in the console, and a per-action circuit breaker can demote an action to review at any time (it only moves down automatically; only a human restores it). Re-check with list_actions rather than caching gears for long sessions.

Write tools under a review gear: pending / refused

When an MCP write tool targets an action whose gear is review, the call does not execute the side effect. It returns a structured result: either the proposal was queued for human approval (pending), or it was refused outright (refused) with a machine-readable reason_code and a suggested_action.

// proposed — waiting for a human
{
  "status": "pending",
  "proposal_id": "prop_9f2c…",
  "action": "issue_coupon",
  "expires_at": "2026-07-10T00:00:00Z",  // 7 days
  "message": "Queued for human approval in
              AI Activity & Approvals."
}
// refused — with a reason and a next step
{
  "status": "refused",
  "action": "issue_coupon",
  "reason_code": "recently_rejected",
  "suggested_action": "A human rejected this
    proposal recently. Do not re-propose;
    consider a different action or ask the
    operator."
}
reason_codeMeaningWhat your agent should do
gear_forbiddenThe action's gear is set to forbidden for this workspace (or the action can never be automatic — e.g. sending — and was invoked in a way that requires auto).Don't retry. Surface the refusal; follow suggested_action (typically an alternative action or 'ask a human to change the gear').
recently_rejectedA human recently rejected the same proposal for the same target — the platform won't re-queue it.Respect the human decision. Don't re-propose or re-word it; follow suggested_action.

Every refusal carries a reason_code in this shape plus a suggested_action — treat the codes above as the ones to branch on and the field as extensible. A refusal is a hard boundary read for you, not an error to retry around: never re-word a proposal to slip past a refusal.

The approval lifecycle

A pending proposal resolves exactly one way: approved, rejected, or expired. Humans act on it in the AI Activity & Approvals console (single or batch by action type); a daily digest email surfaces what's waiting.

StateHow it happensThen
pendingA write tool was called while the action's gear is review — the proposal is queued for human approval.approved · rejected · expired
approvedA human approved it. Before executing, the platform re-validates the AI's stated reasoning; if it no longer holds (e.g. the customer already repurchased), the action is not executed.terminal (result recorded in the decision log; individually revocable)
rejectedA human rejected it, optionally with a note. The same proposal is then refused with recently_rejected if re-submitted.terminal
expiredNo decision within 7 days — the proposal expires on its own and nothing executes.terminal

Idempotency guarantees

  • One approval, one execution. Approving a proposal executes its action exactly once; a repeated approval replays the stored result with no second side effect.
  • Re-submitting doesn't duplicate. Calling the write tool again for the same proposal while it is pending returns the same pending result and proposal_id — it does not queue a second card.
  • Approval re-validates, execution is conditional.At approval time the platform re-checks whether the AI's stated reasoning still holds; if it no longer does (the customer already repurchased, for example), nothing executes — the outcome is recorded instead of the action.
  • Everything is audited and individually revocable. Proposal, decision, authorization path (auto or a named human), execution and result all land in the decision log, where a single entry can be undone.

The server is the boundary.Gears, re-validation, expiry and the per-action circuit breaker are enforced on Flash's side — never trusted to the agent's reasoning or its client-side confirmation. Sending-type actions can never run automatically, whatever the client asks for.