Lesson 21: Task API Observability
This lesson demonstrates how to gain insight into the execution of a task by listening to the full range of events emitted by the Task API's streaming interface.
Code: lesson_21_task_observability.mjs
This script executes a code generation task using `.stream()` and uses a `switch` statement to handle and log every possible event type, including `ExecutionMetadata`, `QuotaMetadata`, and `FinishMetadata`.
// lesson_21_task_observability.mjs
// Merci SDK Tutorial: Lesson 21 - Task API Observability via Streaming Events
// --- IMPORTS ---
import { MerciClient } from '../lib/merci.2.14.0.mjs';
import { token } from '../secret/token.mjs';
const TASK_ID = 'code-generate:default';
async function main() {
console.log(`--- Merci SDK Tutorial: Lesson 21 - Task API Observability (Task: ${TASK_ID}) ---`);
try {
// --- STEP 1: INITIALIZE THE CLIENT ---
console.log('[STEP 1] Initializing MerciClient...');
const client = new MerciClient({ token });
// --- STEP 2: DEFINE TASK PARAMETERS ---
console.log('
[STEP 2] Defining simple parameters for the task...');
const taskParameters = {
instructions: "Write a Python function to calculate the factorial of a number using recursion.",
language: "python",
prefix: "",
suffix: ""
};
// --- STEP 3: STREAM THE TASK AND HANDLE ALL EVENT TYPES ---
console.log(`
[STEP 3] Executing task "${TASK_ID}" with .stream() and listening for all event types...`);
let finalContent = '';
const stream = client.tasks.stream(TASK_ID, taskParameters);
for await (const event of stream) {
// We use a switch statement to handle each event type differently.
switch (event.type) {
case 'Content':
// This is the actual output of the task.
finalContent += event.content;
break;
case 'ExecutionMetadata':
// This provides insight into the internal state or progress of the task.
console.log(`\n[OBSERVABILITY] Received ExecutionMetadata:`, event.data);
break;
case 'QuotaMetadata':
// This tells you about token usage for the task.
console.log(`\n[OBSERVABILITY] Received QuotaMetadata:`, event.data);
break;
case 'FinishMetadata':
// This confirms the task has finished and provides the reason.
console.log(`\n[OBSERVABILITY] Received FinishMetadata: Task finished with reason '${event.data.reason}'`);
break;
case 'FunctionCallMetadata':
// Some tasks might internally call functions and report them.
console.log(`\n[OBSERVABILITY] Received FunctionCallMetadata:`, event.data);
break;
case 'UnknownMetadata':
// Future-proofing: handle any new, unknown metadata types gracefully.
console.log(`\n[OBSERVABILITY] Received UnknownMetadata:`, event.data);
break;
default:
// Log any other event types that might be added in the future.
console.log(`\n[INFO] Received unhandled event type: ${event.type}`);
}
}
console.log('
[INFO] Stream finished.');
// --- STEP 4: DISPLAY THE FINAL GENERATED CONTENT ---
console.log('
--- FINAL RESULT ---');
console.log('Final generated content from the task:\n');
console.log(finalContent);
console.log('
By observing the metadata events, you can build more robust applications that monitor progress and resource usage.');
} catch (error) {
console.error('
[FATAL ERROR] An error occurred during the operation.');
console.error(' Message:', error.message);
if (error.status) {
console.error(' API Status:', error.status);
}
if (error.details) {
console.error(' Details:', JSON.stringify(error.details, null, 2));
}
console.error('
Possible causes: Invalid token, network issues, or an API service problem.');
process.exit(1);
}
}
main().catch(console.error);
Expected Output
The output shows not only the generated code but also a log of all the metadata events that occurred during the task's execution, providing a clear picture of the process and resource usage.
--- Merci SDK Tutorial: Lesson 21 - Task API Observability (Task: code-generate:default) ---
[STEP 1] Initializing MerciClient...
[STEP 2] Defining simple parameters for the task...
[STEP 3] Executing task "code-generate:default" with .stream() and listening for all event types...
[OBSERVABILITY] Received ExecutionMetadata: { ... }
[OBSERVABILITY] Received QuotaMetadata: { ... }
[OBSERVABILITY] Received FinishMetadata: Task finished with reason 'end_turn'.
[INFO] Stream finished.
--- FINAL RESULT ---
Final generated content from the task:
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
By observing the metadata events, you can build more robust applications that monitor progress and resource usage.