Skip to main content

Overview

The endStep function ends an active step, optionally updating its evaluation and other properties before completion.

Syntax

await lai.endStep(params?: {
  stepId?: string;
  state?: string;
  action?: string;
  goal?: string;
  evalScore?: number;
  evalDescription?: string;
}): Promise<void>

Parameters

params
EndStepParams
Optional object with the following properties:

Returns

Returns a Promise that resolves to void.

Examples

Basic Usage

// End current step with no parameters
await lai.endStep();

// End with evaluation
await lai.endStep({
  evalScore: 95,
  evalDescription: "Successfully completed task"
});

// End with evaluation
await lai.endStep({ evalScore: 100, evalDescription: "All objectives met" });

End Specific Step

// Keep reference to step
const step1 = await lai.createStep({ state: "Step 1" });
const step2 = await lai.createStep({ state: "Step 2" });

// End specific step by ID
await lai.endStep({
  stepId: step1.stepId,
  evalScore: 90
});

// Current active step is still step2
await lai.endStep({
  evalScore: 95
});

Error Handling Pattern

await lai.createStep();

try {
  const result = await riskyOperation();
  
  // Success case
  await lai.endStep({ evalScore: 100, evalDescription: "Operation successful" });
  
} catch (error) {
  // Failure case
  await lai.endStep({ evalScore: 0, evalDescription: `Failed: ${error.message}` });
  throw error;
}

With Conditional Scoring

async function processDataWithScoring(data: any[]) {
  await lai.createStep();

  const results = await processItems(data);
  
  // Calculate score based on results
  const successRate = results.filter(r => r.success).length / results.length;
  const score = Math.round(successRate * 100);
  
  await lai.endStep({
    evalScore: score,
    evalDescription: `Processed ${results.length} items, ${score}% success rate`,
    state: `Completed with ${results.filter(r => !r.success).length} failures`
  });
}

Sequential Steps with Evaluation

const steps = [
  { name: "Load", fn: loadData },
  { name: "Validate", fn: validateData },
  { name: "Transform", fn: transformData },
  { name: "Save", fn: saveData }
];

for (const step of steps) {
  await lai.createStep({
    state: `Starting ${step.name}`,
    action: step.name
  });
  
  const startTime = Date.now();
  
  try {
    await step.fn();
    const duration = Date.now() - startTime;
    
    await lai.endStep({ evalScore: 100, evalDescription: `${step.name} completed in ${duration}ms` });
    
  } catch (error) {
    await lai.endStep({ evalScore: 0, evalDescription: `${step.name} failed: ${error.message}` });
    break;
  }
}

Best Practices

1. Always End Steps

// Use try-finally
try {
  await lai.createStep({ state: "Processing" });
  await doWork();
} finally {
  await lai.endStep();
}

// Or use proper error handling
await lai.createStep({ state: "Processing" });
try {
  await doWork();
  await lai.endStep({ evalScore: 100 });
} catch (error) {
  await lai.endStep({ evalScore: 0 });
  throw error;
}

2. Meaningful Evaluations

// Good - specific and actionable
await lai.endStep({
  evalScore: 75,
  evalDescription: "Found 3 of 4 required documents, missing user consent form"
});

// Less helpful
await lai.endStep({
  evalScore: 75,
  evalDescription: "Partially complete"
});

3. Use Context Managers for Self-Contained Workflows

Prefer withLucidic when a session should end at the end of the workflow. See Session Context.

Notes

  • If no stepId is provided, ends the current active step
  • Steps are automatically ended when the session ends
  • All parameters are optional - you can call with no arguments
  • The step must exist and not already be ended

See Also