AI Agents
An agent in Curiosity Workspace is a saved configuration that pairs a system prompt with a list of tools and a chat model. You give it a goal in natural language, the model picks tools, the runtime executes them under the user's permissions, and you get a structured result back — or another agent's output, if you're chaining.
Agents are first-class objects: stored as graph nodes, manageable from Management → Agents, callable from any endpoint or AI tool, and exportable as code for promotion across environments.
Unknown component: alert If you've already shipped AI Tools, agents are the next layer up: a way to package a prompt + a curated tool set + a model into a single re-usable unit you can invoke programmatically. [!/alert]
How an agent runs
The runtime is single-shot, non-streaming, and persists every invocation as an _AgentRun node — so you can audit, replay, or inspect what the model decided. Each run has a Running, Completed, Canceled, or Failed status and a default 5-minute timeout.
When to use an agent vs. an AI tool vs. an endpoint
| Need | Use |
|---|---|
| A deterministic, permission-aware piece of business logic over HTTP | Custom endpoint |
| A function the chat assistant can call mid-conversation | AI tool |
| A reusable LLM workflow with a fixed prompt + tools + model | Agent (this section) |
| A complex task that needs another agent to do part of the work | Sub-agent pattern — see Sub-agent workflows |
A good rule of thumb: an agent is what you'd ship if a non-engineer asked for "a button that summarises this customer's open tickets and writes a draft reply." The behaviour is fixed; only the input changes.
In this section
Creating Agents
Define an agent: system prompt with ${variables}, attached tools, chat model, and optional structured output schema.
Calling from an Endpoint
Invoke AgentAI.RunAgentAsync from a custom endpoint, pass variables, await the result, and return a typed response to the caller.
Anatomy of an agent
| Property | Type | Meaning |
|---|---|---|
Name |
string |
Display name. Surfaced in the management UI and _AgentRun audit log. |
Description |
string |
One-liner describing the agent's purpose. Used as the tool description when the agent is exposed as an InvokeAgent sub-agent. |
SystemPrompt |
string |
The instruction prompt for the model. Supports ${VAR} placeholders bound at call time. |
ChatTaskUID |
UID128 |
The scheduled task that supplies the chat model (provider + parameters). default falls back to the caller's default provider. |
OutputSchema |
string (optional) |
Name of a C# type marked with [AgentOutputSchema] — the runtime forces the model to return JSON conforming to it. |
| Attached tools | edges | Any subset of the workspace's _ChatAITool nodes. Tools are filtered per-call by the caller's ACL. |
Agents are persisted as _Agent graph nodes; the wire DTO is Mosaik.Shared.Agent. The runtime entry point on the server side is the static Mosaik.AI.AgentAI class.
Quick example
A "ticket triage" agent that searches the knowledge base, picks a category, and proposes a next action:
[agent: Curiosity.Agents.Name("Ticket Triage")]
[agent: Curiosity.Agents.Description("Categorise a support ticket and propose the next action.")]
[agent: Curiosity.Agents.Icon("ticket")]
[agent: Curiosity.Agents.ChatTask("01HQ…")] // model/provider task UID
[agent: Curiosity.Agents.OutputSchema("TriageDecision")]
[agent: Curiosity.Agents.Tool("01HZ…")] // SearchTickets
[agent: Curiosity.Agents.Tool("01J0…")] // SearchKB
You triage incoming support tickets for ${PRODUCT}.
Given the ticket body, call SearchTickets to find similar past cases
and SearchKB to find resolution articles. Then return a TriageDecision.
Never invent resolutions — only suggest articles you have cited.
Invocation from an endpoint:
var runUID = await AgentAI.RunAgentAsync(
graph: Graph.Underlying,
agentUID: AI_Agents.Ticket_Triage,
userMessage: Body, // ticket body
userUID: CurrentUser,
variables: new Dictionary<string, string> { ["PRODUCT"] = "MacBook Air" },
cancellationToken: CancellationToken);
var run = Graph.GetReadOnlyContent<_AgentRun>(runUID);
return Ok(run.Result, "application/json");
The next pages walk through each piece in detail.
See also
- AI Tools — the tool surface agents call into.
- LLM Agents and Integration — architectural background on the tool-use loop.
- Custom Endpoints — where agent invocations live.
- RAG and agent architecture.