HUMANin theLOOP

Envelope

Canonical ApprovalEnvelope and Decision types.

Every plugin maps in and out of one shape owned by @hitly/core.

type PluginId = 'mastra' | 'http' | 'langgraph' | 'temporal' | 'hermes'
type Decision = 'accept' | 'reject' | 'edit' | 'respond' | 'ignore' | 'cancel'

interface ApprovalEnvelope {
  action: { name: string; args: Record<string, unknown> }
  allowedActions: Record<Decision, boolean>
  contextMarkdown?: string
  metadata?: Record<string, unknown>
  externalUrls?: string[]
  attachments?: { name: string; url?: string; contentType?: string }[]
  resumeSchema?: Record<string, unknown>
  expiresAt?: string
}

interface OriginRef {
  plugin: PluginId
  projectId: string
  runId: string
  stepId?: string
  resumeHandle: Record<string, unknown>
}

resumeHandle is opaque per plugin (Mastra base URL + run/step ids, Hermes request/task ids, HTTP resumeUrl + optional metadata, LangGraph thread id, Temporal workflow id). Origin credentials live on the project.

HTTP ingest may include metadata (a JSON object). It is stored on the envelope and echoed unchanged on the resume POST for both accept and reject, next to decision and the Hitly id.

See Projects and the API.