Tool Prompt Architecture
Agent tools in Loquent separate what a tool does (sent to the AI provider as the tool definition) from how the agent should use it (appended to the system prompt as behavioral instructions). This keeps tool descriptions concise for the provider while giving the agent detailed rules in the prompt.
The Builder Pattern
Section titled “The Builder Pattern”Each tool builder returns a tuple:
fn build_tool() -> (AgentToolDefinition, String)AgentToolDefinition— concise, factual description sent to the AI providerString— markdown section with behavioral rules appended to the system prompt
Conditional tools return Option<(AgentToolDefinition, String)> and yield None when prerequisites aren’t met (no knowledge bases linked, no transfer numbers configured, etc.).
Tool Builders
Section titled “Tool Builders”end_call (always enabled)
Section titled “end_call (always enabled)”File: src/mods/agent/services/build_end_call_tool_definition_service.rs
pub fn build_end_call_tool_definition() -> (AgentToolDefinition, String)- Description: “Ends the current phone call.”
- Parameters: None
- Prompt section:
### Ending the Call- Say goodbye and IMMEDIATELY call `end_call`.- Do NOT wait for the caller to respond after your farewell.- Do NOT announce that you are ending the call.lookup_caller (conditional)
Section titled “lookup_caller (conditional)”File: src/mods/agent/services/build_client_lookup_tool_definition_service.rs
pub async fn build_client_lookup_tool_definition( organization_id: Uuid,) -> Result<Option<(AgentToolDefinition, String)>, AppError>Returns None when the organization has no client_lookup_url configured.
- Description: “Retrieves the caller’s client record from the database.”
- Parameters: None (caller phone number is automatic)
- Prompt section: Instructs the agent to call
lookup_callerproactively at conversation start and personalize the greeting with the returned data.
query_knowledge (conditional)
Section titled “query_knowledge (conditional)”File: src/mods/agent/services/build_knowledge_tool_definition_service.rs
pub async fn build_knowledge_tool_definition( agent_id: String,) -> Result<Option<(AgentToolDefinition, String)>, AppError>Returns None when the agent has no linked knowledge bases.
- Description: Includes a dynamic list of available knowledge bases and their documents
- Parameters:
query(string) — natural language search query - Prompt section: Instructs the agent to always search knowledge bases before answering covered topics and never guess.
transfer_call (conditional)
Section titled “transfer_call (conditional)”File: src/mods/agent/services/build_transfer_call_tool_definition_service.rs
pub fn build_transfer_call_tool_definition( settings: Option<TransferCallSettings>,) -> Option<(AgentToolDefinition, String)>Returns None when settings is missing or has no numbers. The tool is never registered without at least one configured number.
- Description: “Transfers the current call to another phone number (cold transfer).”
- Parameters:
phone_number(string) — restricted viaenumto configured numbers only - Prompt section: Lists available destinations by label and instructs the agent to confirm before transferring.
Prompt Assembly
Section titled “Prompt Assembly”collect_agent_tools in src/mods/agent/services/collect_agent_tools_service.rs orchestrates all builders:
pub async fn collect_agent_tools( agent_id: String, organization_id: Uuid, tool_config: &AgentToolConfig,) -> Result<(Vec<AgentToolDefinition>, String), AppError>It collects all enabled tools and concatenates their prompt sections under a ## Available Tools heading:
## Available Tools
### Knowledge Base- ALWAYS call `query_knowledge` before answering covered topics.- Do NOT guess — use the tool.
### Call Transfer (CONFIRMATION_FIRST)- Transfer destinations: - +12125551234 — Sales - +12125559876 — Support- ALWAYS confirm with the caller before transferring.
### Ending the Call- Say goodbye and IMMEDIATELY call `end_call`.Both the OpenAI and Gemini session config builders append this addendum to the agent’s base prompt:
let (agent_tools, prompt_addendum) = collect_agent_tools(agent_id, organization_id, &tool_config).await?;
let instructions = format!("{base_prompt}\n\n{prompt_addendum}");Transfer Number Validation
Section titled “Transfer Number Validation”The transfer_call tool enforces that at least one phone number is configured at three levels:
| Level | Behavior |
|---|---|
| Backend | build_transfer_call_tool_definition returns None without valid numbers — tool never registers |
| Validation | AgentToolConfig::validation_error() returns an error message when transfer is enabled but no numbers exist |
| UI | Save button is disabled and inline error text appears below the transfer numbers section |
// AgentToolConfig::validation_error()pub fn validation_error(&self) -> Option<&'static str> { if self.is_tool_enabled("transfer_call") { let has_valid_number = self .get_tool_settings::<TransferCallSettings>("transfer_call") .is_some_and(|s| s.numbers.iter().any(|n| !n.number.trim().is_empty())); if !has_valid_number { return Some("Transfer Call requires at least one phone number."); } } None}Adding a New Tool
Section titled “Adding a New Tool”- Create a builder in
src/mods/agent/services/returning(AgentToolDefinition, String)orOption<(...)> - Write a concise, factual
descriptionfor the tool definition - Write a markdown
### Sectionwith behavioral rules for the prompt - Register the builder in
collect_agent_tools— gate it withtool_config.is_tool_enabled("your_tool") - Add the tool name to the UI toggle list in
tool_config_form_component.rs
Key Files
Section titled “Key Files”| File | Purpose |
|---|---|
src/mods/agent/services/collect_agent_tools_service.rs | Orchestrates builders, assembles prompt addendum |
src/mods/agent/services/build_*_tool_definition_service.rs | Individual tool builders |
src/mods/agent/types/agent_tool_config_type.rs | AgentToolConfig with validation_error() |
src/mods/agent/types/transfer_call_settings_type.rs | TransferCallSettings, TransferNumber |
src/mods/agent/components/tool_config_form_component.rs | UI for tool toggles and transfer number management |