Overview

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

Syntax

await lai.endStep(params?: EndStepParams): 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 full update
await lai.endStep({
  state: "Processing complete",
  action: "Generated report",
  goal: "Deliver insights",
  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({
  state: "Risky operation",
  action: "Process external data"
});

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

With Conditional Scoring

async function processDataWithScoring(data: any[]) {
  await lai.createStep({
    state: "Processing batch",
    action: "Validate and transform"
  });

  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. Update State on Completion

await lai.createStep({
  state: "Search initiated",
  action: "Query database"
});

const results = await searchDatabase();

// Update state to reflect outcome
await lai.endStep({
  state: `Found ${results.length} matching records`,
  evalScore: results.length > 0 ? 100 : 50,
  evalDescription: results.length > 0 
    ? "Search successful" 
    : "No results found"
});

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