Agent Modes
Agent modes determine how a trik integrates with your main agent. This is the core architectural decision when building a trik.
The Two Modes
| Mode | How It Works | Main Agent Sees | Handoff? |
|---|---|---|---|
| Conversational | Full LLM agent, multi-turn conversations | Session summary (from log templates) | Yes |
| Tool | Native tools exported to main agent | Output template (filled with constrained values) | No |
Conversational Mode
Use conversational mode when your trik needs to have a multi-turn conversation, make decisions, or orchestrate multiple tool calls autonomously.
How It Works
- Main agent decides to hand off by calling
talk_to_<trik_id>with context - Gateway routes messages to the trik’s LLM agent
- Trik processes messages, calls its own tools, builds up a response
- Trik calls
transfer_backwhen done - Gateway builds a session summary from log entries and injects it into main agent history
Manifest
{
"agent": {
"mode": "conversational",
"handoffDescription": "Search for articles on any topic. Finds relevant articles, provides summaries, and can retrieve full content.",
"systemPromptFile": "./system-prompt.md",
"model": {
"provider": "anthropic",
"capabilities": ["tool_use"],
"temperature": 0.3
},
"domain": ["content search", "article curation"]
},
"tools": {
"searchArticles": {
"description": "Search for articles by topic",
"logTemplate": "Searched for '{{topic}}' — found {{count}} results",
"logSchema": {
"topic": { "type": "string", "maxLength": 50 },
"count": { "type": "integer", "minimum": 0 }
}
}
}
}Implementation
Conversational triks use wrapAgent() from @trikhub/sdk to bridge a LangGraph agent to the TrikHub protocol:
import { ChatAnthropic } from '@langchain/anthropic';
import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { wrapAgent, transferBackTool } from '@trikhub/sdk';
// Define your trik's tools (these are internal — not exposed to the main agent)
const searchArticlesTool = /* ... your LangChain tool ... */;
const getArticleTool = /* ... your LangChain tool ... */;
// Create the agent with your tools + transferBackTool
const agent = createReactAgent({
llm: new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }),
tools: [searchArticlesTool, getArticleTool, transferBackTool],
});
// Wrap and export
export default wrapAgent(agent);If your agent needs configuration at runtime (e.g., API keys), use the factory pattern:
export default wrapAgent(async (context) => {
const llm = new ChatAnthropic({
apiKey: context.config.get('ANTHROPIC_API_KEY'),
});
return createReactAgent({
llm,
tools: [searchArticlesTool, getArticleTool, transferBackTool],
});
});What the Main Agent Sees
During the handoff, the main agent does not see any of the trik’s messages or tool calls. After the trik calls transfer_back, the gateway builds a summary from log entries:
[System: Trik handoff completed. Session summary:
- Searched for 'AI' — found 12 results
- Retrieved article art-001]This summary is injected into the main agent’s message history so it has context for future turns.
One Handoff at a Time
Only one conversational trik can be active at any given time. While a handoff is active, all user messages go directly to that trik — the main agent is not involved.
To switch to a different trik, the current handoff must end first. This happens when:
- The trik calls
transfer_back(it decided it’s done or the request is outside its domain) - The user types
/backto force a return to the main agent
Once back with the main agent, it can then hand off to a different trik. Triks cannot hand off directly to each other — they are isolated and have no knowledge of other installed triks.
If a user asks a trik to do something outside its domain, the trik should call transfer_back. The user will then need to repeat their request to the main agent, which can route it to the appropriate trik.
Key Properties
- Has its own LLM (defined by
modelpreferences) - Manages multi-turn conversations within the handoff
- Uses
transferBackToolto signal completion - Session and storage capabilities are available
- Security via
logSchema+logTemplate(constrained summaries) - The user sees the trik’s responses directly during the handoff
Tool Mode
Use tool mode when your trik provides straightforward operations that do not need an LLM or multi-turn conversation. The tools appear as native tools on the main agent.
How It Works
- Gateway loads the trik and registers its tools on the main agent
- Main agent calls the tool directly (no handoff, no routing)
- Gateway validates input against
inputSchema - Trik executes the tool and returns structured output
- Gateway validates output against
outputSchema, strips extra properties - Gateway fills
outputTemplateand returns the text to the main agent
Manifest
{
"agent": {
"mode": "tool",
"domain": ["weather", "forecasting"]
},
"tools": {
"getWeather": {
"description": "Get current weather for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": { "type": "string", "minLength": 1 }
},
"required": ["city"]
},
"outputSchema": {
"type": "object",
"properties": {
"temperature": { "type": "integer" },
"unit": { "type": "string", "enum": ["celsius", "fahrenheit"] },
"condition": { "type": "string", "enum": ["sunny", "cloudy", "rainy", "snowy", "windy"] }
},
"required": ["temperature", "unit", "condition"]
},
"outputTemplate": "Current weather: {{temperature}} {{unit}}, {{condition}}"
}
}
}Implementation
Tool-mode triks use wrapToolHandlers() from @trikhub/sdk:
import { wrapToolHandlers } from '@trikhub/sdk';
export default wrapToolHandlers({
getWeather: async (input, context) => {
const { city } = input as { city: string };
const apiKey = context.config.get('WEATHER_API_KEY');
// Call your external API
const data = await fetchWeather(city, apiKey);
return {
temperature: data.temp,
unit: 'celsius',
condition: data.condition,
};
},
});What the Main Agent Sees
The main agent sees the tool as a native tool and receives the filled template:
Current weather: 22 celsius, sunnyThe raw output object is never exposed. Only the template text, filled with validated and property-stripped values, reaches the main agent.
Key Properties
- No LLM inside the trik
- No handoff, no session state
- Tools appear as native tools on the main agent
- Simpler to build and test
- Security via
outputSchema+outputTemplate(agent-safe types only) - Stricter type requirements: string fields need
enum,format, orpattern(maxLengthalone is not sufficient)
Choosing the Right Mode
Does the trik need to have a multi-turn conversation?
├── Yes → Conversational mode
│ └── Does it need to make decisions, orchestrate tools, or adapt?
│ ├── Yes → Conversational mode (with systemPrompt guiding behavior)
│ └── No → Consider tool mode instead
└── No → Tool mode
└── Is it a simple input → output operation?
├── Yes → Tool mode (simpler, tighter security)
└── No → Conversational mode (more flexibility)Quick Comparison
| Aspect | Conversational | Tool |
|---|---|---|
| LLM in trik | Yes | No |
| Handoff | Yes (talk_to_<trik>) | No (direct tool call) |
| Multi-turn | Yes | No |
| Session/Storage | Available | Not available |
| Security model | logSchema + logTemplate | outputSchema + outputTemplate |
| String constraints | enum, format, pattern, maxLength | enum, format, pattern (not maxLength) |
| SDK function | wrapAgent() | wrapToolHandlers() |
| Complexity | Higher | Lower |
| Example use cases | Research assistant, code reviewer, customer support | Weather lookup, currency conversion, data validation |
When to Use Conversational Mode
- The trik needs to ask clarifying questions
- Multiple tools need to be orchestrated in sequence
- The trik needs context from previous turns
- The operation requires judgment or decision-making
- You want the trik to have its own “personality” via system prompt
When to Use Tool Mode
- Simple input/output operations (lookups, calculations, validations)
- The main agent should decide when and how to use the tool
- You want the tightest possible security boundary
- No multi-turn interaction is needed
- You want the simplest possible implementation
Next: Understand the Security Model behind these modes.