Patterns
Organize Runiq tools cleanly in a .NET application.
Keep tools close to the .NET capability they expose.
For a real application, create a Tools folder and put each tool in its own file or small feature folder. A tool should look like application code: typed input, typed output, dependency injection, validation, and one focused operation.
Tools are not prompt fragments. They are native .NET capabilities that agents can call through the Runiq runtime.
Recommended project layout
For a larger domain, group tool models with the tool:
For the travel sample:
Travel is only the sample domain. The pattern is the important part: tools live in Tools/, and agents attach only the tools they should be allowed to call.
For the expense sample:
This layout is closer to a business application. The tool does not own the data store; it calls the app's data service. The agent receives a business capability, not direct database access.
Keep Program.cs small
Most tools should be attached from agent factories, not wired manually in Program.cs.
Program.cs shows which agents are registered. The agent files show which tools each agent can use.
Use options.AddTool<TTool>() only when you intentionally want a standalone tool available in the dashboard tool playground without attaching it to an agent.
Standalone registration does not grant every agent access to that tool. Agents still need .AddTool<TTool>().
Put tool logic in tool files
A small tool can keep the tool class, input record, and output record in one file.
For larger domains, split the models into separate files. Keep the contract easy to inspect because the model, dashboard, and runtime all depend on that contract.
Attach tools from agent factories
The agent that needs a tool should attach it.
This keeps capability boundaries explicit. Weather Agent can call WeatherTool. Places Agent can call PlacesTool. Planner Agent can call MealSuggestionTool. They do not automatically share every tool in the application.
Use DI for application services
Tools should call your existing application services instead of duplicating infrastructure code.
This keeps AI integration native to the .NET app. The agent gets a safe capability; the tool gets normal C# dependencies.
In a real system, those dependencies might be DbContext, repositories, billing services, CRM clients, authorization checks, or internal APIs. Runiq does not require those services to become prompts. You expose a small typed surface and keep the implementation in C#.
Good fits
Tools work well for read-only lookups, deterministic calculations, curated searches, safe write operations, and policy checks.
Examples:
These are good fits because the input can be modeled, the output can be structured, and the operation belongs to your application.
Common mistakes
Putting tool logic inside Program.cs makes the runtime registration harder to read. Put each tool in Tools/*.cs.
Returning a long final answer from a tool makes the agent less useful. Return structured data and let the agent write the final response.
Using one generic tool for many unrelated actions hides the contract from the model and the dashboard. Split capabilities into focused tools.
Hiding business rules in prompts makes behavior harder to test. Keep business rules in .NET code and expose them through typed tools.
Attaching every tool to every agent weakens the capability boundary. Attach only the tools each agent should use.
Swallowing exceptions and returning fake data makes debugging harder. Fail clearly so the dashboard and model can see what happened.