Dynamic agents allow you to extend Gravity with custom behaviors without writing C# code. They are defined as JSON files and loaded at startup, using the LLM as their reasoning engine while routing tool calls through the shared ReasoningRouter.
JSON Definition Format
{
"name": "my_custom_agent",
"description": "Specialized agent for code review tasks",
"system": "You are an expert code reviewer. Focus on security, performance, and maintainability. Use the code_editor tool to examine files.",
"verbs": ["review", "audit", "analyze"],
"maxSteps": 10,
"canWrite": false,
"parameters": {
"focusAreas": {
"type": "array",
"items": { "type": "string" },
"description": "Areas to focus on: security, performance, style, architecture"
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique identifier (snake_case, used in tool routing) |
description | string | Yes | Human-readable description shown in help |
system | string | Yes | System prompt defining agent behavior |
verbs | string[] | Yes | Trigger verbs for intent routing |
maxSteps | integer | No | Max reasoning iterations (default: 10) |
canWrite | boolean | No | Whether agent can perform write operations (default: false) |
parameters | object | No | JSON schema for agent-specific parameters |
Loading at Startup
- Place
.jsonfiles in theagents/directory next to the executable - On startup,
AgentLoaderscans the directory - Each file is validated against the schema
- Valid agents are registered in the DI container as
IAgentimplementations - Agent descriptors are included in the tool manifest sent to the LLM
Invalid agents are logged but don't block startup.
Tool Call Routing
Dynamic agents use the LLM as their reasoning engine. When the LLM outputs a tool call:
ReasoningRouterintercepts the call- Validates parameters against the action's JSON schema
- Checks approval policy (
IsDestructiveflag) - Routes to the target
IAgent(built-in or MCP) - Returns
AgentResultto the dynamic agent's conversation
This gives dynamic agents access to all built-in tools (file operations, shell, search, etc.) without reimplementing them.
Complete Example: Security Auditor Agent
File: agents/security_auditor.json
{
"name": "security_auditor",
"description": "Performs security-focused code reviews",
"system": "You are a security auditor. Scan for: SQL injection, XSS, path traversal, hardcoded secrets, insecure crypto, missing auth checks. Use code_editor to read files. Report findings with file:line references.",
"verbs": ["audit", "security-review", "scan"],
"maxSteps": 15,
"canWrite": false,
"parameters": {
"severityThreshold": {
"type": "string",
"enum": ["low", "medium", "high", "critical"],
"default": "medium"
},
"includeTests": { "type": "boolean", "default": false }
}
}
Usage in chat: "Audit the Controllers folder for security issues"