Automatisierungsvorschlaege: Agenten schlagen n8n-Workflows vor, der Mensch importiert von Hand (#726)
- Core/Automation/WorkflowReview: free check of an n8n export - every node with its effect and target, code/command/SSH nodes only with a stated reason, embedded secrets refused (by name or by look), a short summary of what the workflow does. - AutomationProposals: measured saving from the replaced tasks' receipts (28 days), at most 3 open per agent, the same purpose not twice, a rejected proposal must be answered; the human gets a task and decides in the approvals view. Accepting records it - importing stays a human's step. - Candidates: recurring tasks whose runs repeat the same calls (>= 75 % of >= 8 runs in 14 days) are put to their agent once a month. - Escalation tool: automation_find, automation_propose. - Approvals view: proposals with nodes, targets, warnings, saving, JSON download, accept/reject. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
64e09b82d5
commit
067ff62317
@@ -375,6 +375,31 @@ internal static class ApiEndpoints
|
||||
result.Kind is Core.Staging.StagingResultKind.Executed, result.Message));
|
||||
});
|
||||
|
||||
// #726: Workflows agents propose — the human decides here and imports by hand in n8n.
|
||||
staging.MapGet("/automations", async (AppHost host, CancellationToken ct, string? status) =>
|
||||
{
|
||||
if (host.Automations is not { } automations)
|
||||
return Results.Ok(Array.Empty<AutomationProposalDto>());
|
||||
return Results.Ok((await automations.ListAsync(status, 50, ct)).Select(p => new AutomationProposalDto(
|
||||
p.Id, p.AgentId, p.Purpose, p.Trigger, p.TaskIds, p.Services, p.Risks, p.TestGuide, p.Justification, p.Summary,
|
||||
p.Nodes.Select(x => new WorkflowNodeDto(x.Name, x.Type, x.Effect, x.Target, x.Dangerous)).ToList(),
|
||||
p.Warnings, p.Savings.Runs, p.Savings.CostUsd, p.Savings.CostPerMonthUsd, p.Savings.RunsPerMonth, p.Savings.Days,
|
||||
p.Status, p.Reason, p.CreatedAt, p.DecidedAt, p.Answers)).ToList());
|
||||
});
|
||||
|
||||
staging.MapGet("/automations/{id:long}/workflow", async (AppHost host, long id, CancellationToken ct) =>
|
||||
host.Automations is { } automations && (await automations.ListAsync(null, 1000, ct)).FirstOrDefault(p => p.Id == id) is { } proposal
|
||||
? Results.Text(proposal.WorkflowJson, "application/json")
|
||||
: Results.NotFound(new OutcomeDto(false, $"No proposal #{id}.")));
|
||||
|
||||
staging.MapPost("/automations/{id:long}/decide", async (AppHost host, long id, AutomationDecisionDto input, CancellationToken ct) =>
|
||||
{
|
||||
if (host.Automations is not { } automations)
|
||||
return Results.BadRequest(new OutcomeDto(false, "Automation proposals are not available in this instance."));
|
||||
var outcome = await automations.DecideAsync(id, input.Accept, input.Reason ?? "", ct);
|
||||
return outcome.Ok ? Results.Ok(new OutcomeDto(true, outcome.Message)) : Results.BadRequest(new OutcomeDto(false, outcome.Message));
|
||||
});
|
||||
|
||||
// #687: How often each lead approved what it was given — a lead that approves everything does nothing.
|
||||
staging.MapGet("/leads", async (AppHost host, CancellationToken ct, int days = 30) =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user