Portal Community

Auto-Capture Trigger

Auto-capture is triggered when all of these conditions are met:

Procedure Extraction

public class ProcedureCaptureService
{
    public async Task CaptureIfEligibleAsync(
        Episode episode,
        AgentComposite agent,
        CancellationToken ct = default)
    {
        if (!agent.MemoryConfig.AutoCaptureEnabled) return;
        if (episode.ToolCalls.Count < 3) return;
        if (!IsPositiveOutcome(episode)) return;

        // Generalize the tool call sequence — extract parameter patterns
        var steps = GeneralizeProcedure(episode.ToolCalls, episode.Messages);

        var candidate = new Procedure
        {
            Name = await _llm.GenerateProcedureNameAsync(episode, ct),
            Description = await _llm.GenerateProcedureDescriptionAsync(episode, ct),
            TriggerPattern = await _llm.ExtractTriggerPatternAsync(episode.Messages, ct),
            Steps = steps,
            AgentId = agent.Id,
            TenantId = agent.TenantId,
            IsApproved = false,  // requires human approval
            CreatedBy = "agent"
        };

        await _store.StoreAsync(candidate, ct);

        // Notify admin that a new procedure candidate is awaiting review
        await _notifier.NotifyProcedureCandidateAsync(candidate);
    }

    private List<ProcedureStep> GeneralizeProcedure(
        List<ToolCallRecord> toolCalls,
        List<LLMMessage> messages)
    {
        return toolCalls.Select((tc, i) => new ProcedureStep
        {
            Order = i + 1,
            ToolName = tc.ToolName,
            // Replace specific values with {{parameter}} placeholders
            ToolArgumentTemplate = Generalize(tc.Input),
            Instruction = ExtractInstruction(messages, tc)
        }).ToList();
    }
}

Parameter Generalization

The capture service replaces specific values from the conversation with typed placeholders:

// Original tool call from the conversation:
{ "vendor_name": "TechCorp", "contact": "john@techcorp.com", "contract": "CTR-2025-001" }

// Generalized template (specific values replaced with placeholders):
{ "vendor_name": "{{vendor_name}}", "contact": "{{contact_email}}", "contract": "{{contract_ref}}" }

// The generalization uses heuristics:
// - Known person names → {{person_name}}
// - Email patterns → {{email_address}}
// - ID patterns (CTR-YYYY-NNN) → {{contract_ref}}
Auto-Capture is a Starting Point, Not an End Point

Auto-captured procedures are always unapproved initially. They require an administrator to review, edit, and approve before they become active. The auto-capture is meant to reduce the effort of writing procedures from scratch — not to create untested automation.