
Running an agent
The common deployment shape is an agent behind a custom endpoint: a thin HTTP wrapper validates input, binds variables, runs the agent, and returns the typed result. The entry point is AgentAI.RunAgentAsync.
public record TriageRequest(string TicketBody, string Product);
var req = Body.FromJson<TriageRequest>();
if (req is null || string.IsNullOrWhiteSpace(req.TicketBody))
return BadRequest("`ticketBody` is required.");
var runUID = await AgentAI.RunAgentAsync(
graph: Graph.Underlying,
agentUID: AI_Agents.Ticket_Triage, // auto-generated constant
userMessage: req.TicketBody,
userUID: CurrentUser, // ACL flows through every tool call
variables: new Dictionary<string, string> { ["PRODUCT"] = req.Product ?? "" },
cancellationToken: CancellationToken);
if (!Graph.TryGetReadOnlyContent<_AgentRun>(runUID, out var run))
return Problem("Run was not persisted.");
if (run.Status != AgentRunStatus.Completed)
return Problem($"Triage failed: {run.ErrorMessage ?? run.Status.ToString()}");
var decision = run.Result.FromJson<TriageDecision>();
return Ok(decision.ToJson(), "application/json");
Three things to get right:
CurrentUser is mandatory |
Never substitute default to "see everything" — tool calls are ACL-filtered as this user |
Check run.Status first |
A Failed run can still carry an unreliable Result |
Long runs → Pooling mode |
Multi-step agents run 10–60s; return 202 and stream progress with RelayStatusAsync(...) |
The _AgentRun node is the audit trail — Status, Result, ErrorMessage, Started/Completed timestamps, and the full Messages transcript for replay. Return Result to the caller; keep the rest in the log (the transcript can expose internal IDs).
No endpoint needed? There's a built-in REST surface for signed-in callers:
POST /api/chatai/agents/run { AgentUID, UserMessage, Variables } → AgentRun
GET /api/chatai/agents/runs/get/{uid} → AgentRun
Prefer the custom-endpoint shape when you need pre/post-processing or your own auth scheme.