Reference Implementations

Interaction

live-session-coach

advanced

Primary Live Interaction Layer reference: interruptible text-live via ctx.live.openSession(), intent supersede, background work, and approval gates.

APIs Used

ctx.livectx.escalate()ctx.llmctx.provenance

Capabilities Required

interaction/coachlive.session.start

What this demonstrates

  • 1ctx.live.openSession({ mode: "text" }) — launch primary agent API
  • 2G1: tentative intent superseded on direction change (no mutation from old hypothesis)
  • 3G2: observational background work while session stays conversational
  • 4G3: ctx.escalate() approval gate before consequential connector invoke
  • 5Provenance for session lifecycle, intent transitions, and overrides
typescript
/**
* Live Session Coach — Live Interaction Layer reference agent
*
* Canon alignment:
* - Launch product API: ctx.live.openSession() (plans/humanos_live_interaction_layer_prd.md)
* - Duplex is internal Conversation Channel plumbing — not the documented agent entry.
* - Demonstrates golden scenarios G1–G3 for agent authors.
*
* G1 — Interruptible planning: supersede tentative intent on direction change
* G2 — Background work while present: presence stays conversational while work runs
* G3 — Approval before consequential action: escalate before connector invoke
*/
import { handler, withProvenanceContext } from '@human/agent-sdk';
import type { ExecutionContext } from '@human/agent-sdk';
import {
transitionIntentStatus,
assertIntentActionable,
type IntentHypothesis,
} from '@human/interaction';
import { RunState } from '@human/core';
import { randomUUID } from 'node:crypto';
export const AGENT_ID = 'live-session-coach';
export const VERSION = '1.0.0';
export const CAPABILITIES = [
'live.session.start',
'live.session.intent.propose',
'live.session.work.background',
'live.session.override',
'interaction/coach',
];
export interface LiveSessionTurn {
utterance: string;
/** G1: supersede the prior tentative intent with a new goal inferred from this turn. */
supersede?: boolean;
/** G2: start background work while presence stays conversational (intent must be confirmed before connectors). */
background_work?: boolean;
/** G3: consequential action label — triggers approval gate before any send. */
consequential_action?: string;
/** Simulates override reflex: cancel pending approval/work. */
cancel_pending?: boolean;
}
export interface LiveSessionCoachInput {
mode?: 'text' | 'voice';
provider?: string;
turns?: LiveSessionTurn[];
maxDurationSecs?: number;
}
export interface LiveSessionCoachOutput {
success: boolean;
live_session_id: string;
turn_count: number;
intents_proposed: number;
intents_superseded: number;
background_work_started: boolean;
approval_status: 'none' | 'pending' | 'approved' | 'rejected' | 'cancelled';
stopped_reason: 'natural_end' | 'max_duration' | 'error';
provenance_id: string;
}
export async function execute(
ctx: ExecutionContext,
input: LiveSessionCoachInput,
): Promise<LiveSessionCoachOutput> {
const mode = input.mode ?? 'text';
const turns = input.turns ?? [];
const maxDurationSecs = input.maxDurationSecs ?? 300;
let intentsProposed = 0;
let intentsSuperseded = 0;
let backgroundWorkStarted = false;
let approvalStatus: LiveSessionCoachOutput['approval_status'] = 'none';
let activeIntent: IntentHypothesis | null = null;
let pendingApprovalId: string | null = null;
let stoppedReason: LiveSessionCoachOutput['stopped_reason'] = 'natural_end';
try {
const session = await ctx.live.openSession({
mode,
provider: input.provider ?? 'mock',
});
ctx.log.info('LiveSession opened', {
live_session_id: session.live_session_id,
mode: session.mode,
});
await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.session.started',
status: 'success',
input: { mode, provider: input.provider ?? 'mock' },
output: { live_session_id: session.live_session_id },
}),
);
const deadline = Date.now() + maxDurationSecs * 1000;
for (const turn of turns) {
if (Date.now() > deadline) {
stoppedReason = 'max_duration';
break;
}
if (turn.cancel_pending) {
pendingApprovalId = null;
approvalStatus = 'cancelled';
await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.session.override.cancel_pending',
status: 'success',
input: { utterance: turn.utterance },
output: { live_session_id: session.live_session_id },
}),
);
continue;
}
const inferredGoal = inferGoal(turn.utterance);
if (activeIntent && turn.supersede) {
const superseded = transitionIntentStatus(activeIntent, 'superseded', {
superseded_by: 'pending',
});
intentsSuperseded++;
await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.intent.superseded',
status: 'success',
input: { old_goal: activeIntent.inferred_goal, new_utterance: turn.utterance },
output: { hypothesis_id: superseded.hypothesis_id },
}),
);
activeIntent = null;
}
const hypothesis: IntentHypothesis = {
hypothesis_id: randomUUID(),
live_session_id: session.live_session_id,
confidence: 0.72,
inferred_goal: inferredGoal,
likely_actions: inferLikelyActions(turn),
risk_level: turn.consequential_action ? 'high' : 'low',
requires_approval: Boolean(turn.consequential_action),
required_capabilities: turn.consequential_action ? ['connector.email.send'] : [],
status: 'tentative',
};
activeIntent = hypothesis;
intentsProposed++;
await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.intent.proposed',
status: 'success',
input: { utterance: turn.utterance },
output: { hypothesis_id: hypothesis.hypothesis_id, inferred_goal: inferredGoal },
}),
);
if (turn.background_work) {
backgroundWorkStarted = true;
await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.work.background.started',
status: 'success',
input: { label: 'deck_analysis', work_kind: 'background_analysis' },
output: {
live_session_id: session.live_session_id,
run_state: RunState.Executing,
},
}),
);
}
if (turn.consequential_action) {
const confirmed = transitionIntentStatus(hypothesis, 'confirmed');
activeIntent = confirmed;
assertIntentActionable(confirmed);
const escalation = await ctx.escalate({
reason: `Consequential action requires approval: ${turn.consequential_action}`,
context: {
live_session_id: session.live_session_id,
hypothesis_id: confirmed.hypothesis_id,
action: turn.consequential_action,
},
waitForDecision: false,
routingMode: 'workforce_cloud',
});
if (escalation.approved) {
approvalStatus = 'approved';
pendingApprovalId = escalation.metadata?.provenanceId ?? null;
} else if (escalation.status === 'pending') {
approvalStatus = 'pending';
pendingApprovalId = escalation.metadata?.provenanceId ?? null;
} else {
approvalStatus = 'rejected';
}
const provenanceStatus =
approvalStatus === 'approved'
? 'success'
: approvalStatus === 'rejected'
? 'error'
: 'started';
await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.approval.gate',
status: provenanceStatus,
input: { action: turn.consequential_action },
output: { approval_status: approvalStatus, approval_id: pendingApprovalId },
}),
);
if (approvalStatus !== 'approved') {
continue;
}
}
const coaching = await analyzeUtterance(ctx, turn.utterance);
if (coaching) {
ctx.log.info('Coaching insight', { insight: coaching });
}
}
const provenanceId = await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.session.completed',
status: 'success',
input: { mode, turn_count: turns.length },
output: {
live_session_id: session.live_session_id,
intents_proposed: intentsProposed,
intents_superseded: intentsSuperseded,
approval_status: approvalStatus,
},
}),
);
return {
success: true,
live_session_id: session.live_session_id,
turn_count: turns.length,
intents_proposed: intentsProposed,
intents_superseded: intentsSuperseded,
background_work_started: backgroundWorkStarted,
approval_status: approvalStatus,
stopped_reason: stoppedReason,
provenance_id: provenanceId,
};
} catch (err) {
ctx.log.error('Live session coach error', { error: err });
const provenanceId = await ctx.provenance.log(
withProvenanceContext(ctx, {
action: 'live.session.completed',
status: 'error',
input: { mode },
output: { error: String(err) },
}),
);
return {
success: false,
live_session_id: 'unknown',
turn_count: turns.length,
intents_proposed: intentsProposed,
intents_superseded: intentsSuperseded,
background_work_started: backgroundWorkStarted,
approval_status: approvalStatus,
stopped_reason: 'error',
provenance_id: provenanceId,
};
}
}
function inferGoal(utterance: string): string {
const lower = utterance.toLowerCase();
if (lower.includes('challenge')) return 'Identify investor challenges';
if (lower.includes('deck') || lower.includes('background')) return 'Analyze presentation deck';
if (lower.includes('send') || lower.includes('email')) return 'Send revised note to investor';
if (lower.includes('prep') || lower.includes('call')) return 'Prepare for investor call';
return `Respond to: ${utterance.slice(0, 80)}`;
}
function inferLikelyActions(turn: LiveSessionTurn): string[] {
if (turn.consequential_action) return [turn.consequential_action];
if (turn.background_work) return ['analyze_deck', 'summarize_risks'];
return ['clarify_goal', 'coach_response'];
}
async function analyzeUtterance(ctx: ExecutionContext, text: string): Promise<string | null> {
if (text.trim().length < 10) return null;
try {
const systemPrompt = await ctx.prompts.load('core/agents/live-session-coach/system');
const result = await ctx.llm.complete({
system: systemPrompt.content,
prompt: `User said: "${text}"\n\nProvide a 1-2 sentence coaching insight for a live session, or empty string if nothing useful.`,
temperature: 0.4,
maxTokens: 80,
promptMetadata: systemPrompt.toCallMetadata(),
});
const trimmed = result.content.trim();
return trimmed.length > 0 ? trimmed : null;
} catch {
return null;
}
}
export default handler({
name: AGENT_ID,
id: AGENT_ID,
version: VERSION,
capabilities: CAPABILITIES,
description:
'Reference agent for LiveSession: interruptible text-live, intent supersede, background work, and approval gates via ctx.live.',
manifest: {
operations: [
{
name: 'coach',
description: 'Open a LiveSession and demonstrate G1–G3 live interaction patterns',
paramsSchema: {
mode: { type: 'string', description: 'text | voice' },
provider: { type: 'string', description: 'Provider (default: mock)' },
turns: { type: 'array', description: 'Simulated conversation turns for demo/tests' },
},
resultKind: 'agent.live-session-coach.result',
},
],
},
execute,
});

Run the tests

From monorepo root

$ pnpm test:agents:reference

$ pnpm test:agents:reference:verbose

The reference suite runs all 23 agents with createMockExecutionContext(), verifying every ctx.* API call and output shape.

See Also