Curiosity

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.

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.

How an agent runs

flowchart LR Caller[Endpoint / AI Tool / REST] --> AgentAI[AgentAI.RunAgentAsync] AgentAI --> Prompt["System prompt<br/>+ user message<br/>+ $&#123;variables&#125;"] Prompt --> LLM[Chat model<br/>ChatTaskUID] LLM -->|tool call| ToolLoop[ChatAITool runtime] ToolLoop -->|result| LLM LLM -->|done| Run[(_AgentRun node:<br/>result + status)] Run --> Caller

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.

Calling from an AI Tool

Wrap an agent as a [Tool] so the main chat assistant can delegate to it — the foundation for the sub-agent pattern.

Sub-agent Workflows

Chain specialised agents through an InvokeAgent tool to build research, summarisation, and aggregation pipelines.

Example Agents

A catalog of ready-to-adapt agents — triage, Q&A with citations, scoring, extraction, and per-node enrichment from a code index. Each entry includes a full system prompt and suggested tool set.

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

© 2026 Curiosity. All rights reserved.