Eingehende Ausloeser: n8n und andere starten Agenten (#725, Stufe 1)

Something outside hands an agent a task - an n8n workflow on a mail, a
schedule, a form, or any system that sends an HTTP request.

- Core/Triggers/InboundTriggers: one token per trigger and agent, kept as a
  hash and shown once; a rate per hour; deliveries up to 64 KB. Each
  delivery becomes a task whose content is framed as foreign content with its
  origin; every delivery, accepted or refused, is in the audit (source
  "trigger").
- POST /hooks/trigger on the instance (MCP socket, own token, no browsers);
  the manager forwards /hooks/{instance}/trigger. /api/triggers to issue,
  list and revoke.
- Agent view: a triggers card with the address and an n8n/curl example.
- Nothing writes back: no right to create or change workflows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-10-01 13:19:05 +02:00
co-authored by Claude Opus 5.5
parent 47a20913b0
commit 73565eff18
14 changed files with 607 additions and 5 deletions
+20
View File
@@ -454,6 +454,26 @@ internal static class ManagerEndpoints
await forwarding.ForwardMcpAsync(context, ziel, ct);
});
// #725: An inbound trigger of an instance — n8n or any system that sends a request. Like
// MCP: no manager token, the trigger's own token is the key, and it goes to the
// instance's MCP socket, which leads to nothing else.
app.MapPost("/hooks/{instanz}/trigger", async (
HttpContext context, string instanz, InstanceRegistry registry, InstanceForwarding forwarding,
CancellationToken ct) =>
{
if (context.Request.Headers.Origin.Count > 0)
{
context.Response.StatusCode = StatusCodes.Status403Forbidden;
return;
}
if (Find(registry, instanz) is not { } ziel)
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
return;
}
await forwarding.ForwardMcpAsync(context, ziel, ct, "/hooks/trigger");
});
app.Map("/api/{**pfad}", async (
HttpContext context, InstanceRegistry registry, InstanceForwarding forwarding,
CancellationToken ct) =>