Skip to main content

Intent modes

Intent modes

HUMΛN separates what the user said this turn from what they want built. Companion chat returns a per-turn classification (question | context | intent). The Intent-to-Capability pipeline (POST /v1/intent) turns durable goals into resolution plans, scaffolds, and provisioning.

Overview

  • question — user wants an answer; render text + citations.
  • context — user is sharing session context; acknowledge only.
  • intent — user wants something done; surface intent_action when present, or loop clarifying turns.

Mis-parsing an intent turn as a question is how you get confident wrong answers instead of governed action.

Per-turn classification (Companion clients)

Every Companion response that participates in governed action includes classification. Branch before you render:

type TurnClassification = 'question' | 'context' | 'intent';

interface CompanionTurn {
  classification: TurnClassification;
  text: string;
  citations?: Array<{ uri: string; title: string }>;
  intent_action?: {
    tool_id: string;
    params: Record<string, unknown>;
    autonomy: 'observe' | 'propose' | 'auto';
    requires_approval: boolean;
    reversible: boolean;
    human_readable: string;
    consequence: string;
    provenance_scope: string;
  } | null;
}

function handleTurn(turn: CompanionTurn) {
  switch (turn.classification) {
    case 'question':
      // Render answer + citations only
      return { mode: 'answer', body: turn.text, citations: turn.citations ?? [] };

    case 'context':
      // Acknowledge — context is persisted server-side
      return { mode: 'ack', body: turn.text };

    case 'intent':
      if (!turn.intent_action) {
        // Fuzzy intent — clarifying question; send next user message back through Companion
        return { mode: 'clarify', body: turn.text };
      }
      // Clear intent — show approval card; call human.call only after explicit approval
      return {
        mode: 'propose',
        body: turn.text,
        approval: {
          title: turn.intent_action.human_readable,
          detail: turn.intent_action.consequence,
          requiresApproval: turn.intent_action.requires_approval,
          toolId: turn.intent_action.tool_id,
          params: turn.intent_action.params,
        },
      };
  }
}

Fourth Law: when requires_approval: true, wait for human respond — do not upgrade autonomy client-side.

Intent-to-Capability API (/v1/intent)

For durable “build this” flows (not just the current chat turn), use IntentClient from @human/sdk:

>
SDK:

Multimodal ingest

Same brief pipeline for voice or pasted docs:

await client.intent.transcribe({
  transcript: 'Keep invoice reconciliation moving every Monday morning',
  source_surface: 'companion',
});

await client.intent.extract({
  document_text: 'Refund policy: auto-approve under $500 with finance review above',
  source_surface: 'workflow_designer',
});

await client.intent.ingest({
  text: 'Automate refund approvals under $500',
  document_text: policyPdfText,
  source_surface: 'agent_builder',
});

Shipped surfaces

Surface Purpose
Companion turn classification Per-message UX branching (question | context | intent)
client.intent.* Intent brief lifecycle — build, shape, compile, provision, lineage
POST /v1/intent Create brief from natural language
POST /v1/intent/:id/compile Capability-first resolution paths
POST /v1/intent/:id/provision Start provisioning from selected path
GET /v1/intent/:id/lineage Audit chain for brief → execution

Implementation: packages/sdk/src/intent.ts, apps/api/src/routes/intent/.

Use cases

  • Embedded Companion widget — parse classification before auto-running tools; show approval cards for intent_action.
  • Builder / CLIintent.buildcompilescaffold for repeatable scaffolding.
  • Control Plane activityclient.intent.adminIntentActivity() for org-scoped brief lists.
  • Clarifying loops — tolerate 2–3 fuzzy intent turns; session is durable.

Security considerations

DO

Branch on classification before invoking tools

Respect requires_approval and server-set autonomy on intent_action

Use intent lineage for audit when provisioning agents or bundles

DON'T

Treat intent_action as optional decoration on intent turns

Auto-execute because autonomy returned auto without checking reversible

Re-use a spent approval_id on human.call

See also

← All patterns