Tool whitelist from agent header filters native tools
The tools field in agent headers now filters which native tools the agent receives. Empty = all tools (default). Non-empty = whitelist. Journal agent can list only journal_tail/journal_new/ journal_update. Log shows actual tool names instead of "no tools". Threaded tools list through call_api_with_tools → sync wrapper → llm caller. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
834247fa53
commit
8eabeab8eb
3 changed files with 20 additions and 9 deletions
|
|
@ -35,6 +35,7 @@ pub async fn call_api_with_tools(
|
||||||
prompts: &[String],
|
prompts: &[String],
|
||||||
phases: &[String],
|
phases: &[String],
|
||||||
temperature: Option<f32>,
|
temperature: Option<f32>,
|
||||||
|
tools: &[String],
|
||||||
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
||||||
log: &dyn Fn(&str),
|
log: &dyn Fn(&str),
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
|
|
@ -43,10 +44,16 @@ pub async fn call_api_with_tools(
|
||||||
// Set up a UI channel — we drain reasoning tokens into the log
|
// Set up a UI channel — we drain reasoning tokens into the log
|
||||||
let (ui_tx, mut ui_rx) = crate::agent::ui_channel::channel();
|
let (ui_tx, mut ui_rx) = crate::agent::ui_channel::channel();
|
||||||
|
|
||||||
// Subconscious agents only get memory tools — no filesystem access.
|
// All available native tools for subconscious agents
|
||||||
// TODO: respect tools whitelist from agent header to filter which
|
let all_tools = thought::memory_and_journal_definitions();
|
||||||
// native tools each agent gets (e.g. journal agent only gets journal tools)
|
// If agent header specifies a tools whitelist, filter to only those
|
||||||
let tool_defs = thought::memory_and_journal_definitions();
|
let tool_defs: Vec<_> = if tools.is_empty() {
|
||||||
|
all_tools
|
||||||
|
} else {
|
||||||
|
all_tools.into_iter()
|
||||||
|
.filter(|t| tools.iter().any(|w| w == &t.function.name))
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
let tracker = ProcessTracker::new();
|
let tracker = ProcessTracker::new();
|
||||||
// Provenance tracks which agent:phase is making writes.
|
// Provenance tracks which agent:phase is making writes.
|
||||||
// Updated between steps by the bail function via set_provenance().
|
// Updated between steps by the bail function via set_provenance().
|
||||||
|
|
@ -226,6 +233,7 @@ pub fn call_api_with_tools_sync(
|
||||||
prompts: &[String],
|
prompts: &[String],
|
||||||
phases: &[String],
|
phases: &[String],
|
||||||
temperature: Option<f32>,
|
temperature: Option<f32>,
|
||||||
|
tools: &[String],
|
||||||
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
||||||
log: &(dyn Fn(&str) + Sync),
|
log: &(dyn Fn(&str) + Sync),
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
|
|
@ -236,7 +244,7 @@ pub fn call_api_with_tools_sync(
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| format!("tokio runtime: {}", e))?;
|
.map_err(|e| format!("tokio runtime: {}", e))?;
|
||||||
rt.block_on(
|
rt.block_on(
|
||||||
call_api_with_tools(agent, prompts, phases, temperature, bail_fn, log)
|
call_api_with_tools(agent, prompts, phases, temperature, tools, bail_fn, log)
|
||||||
)
|
)
|
||||||
}).join().unwrap()
|
}).join().unwrap()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -294,8 +294,11 @@ fn run_one_agent_inner(
|
||||||
_llm_tag: &str,
|
_llm_tag: &str,
|
||||||
log: &(dyn Fn(&str) + Sync),
|
log: &(dyn Fn(&str) + Sync),
|
||||||
) -> Result<AgentResult, String> {
|
) -> Result<AgentResult, String> {
|
||||||
let tools_desc = if def.tools.is_empty() { "no tools".into() }
|
let tools_desc = if def.tools.is_empty() {
|
||||||
else { format!("{} tools", def.tools.len()) };
|
"all tools".into()
|
||||||
|
} else {
|
||||||
|
def.tools.join(", ")
|
||||||
|
};
|
||||||
let n_steps = agent_batch.steps.len();
|
let n_steps = agent_batch.steps.len();
|
||||||
|
|
||||||
for key in &agent_batch.node_keys {
|
for key in &agent_batch.node_keys {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ pub(crate) fn call_simple(caller: &str, prompt: &str) -> Result<String, String>
|
||||||
|
|
||||||
let prompts = vec![prompt.to_string()];
|
let prompts = vec![prompt.to_string()];
|
||||||
let phases = vec![];
|
let phases = vec![];
|
||||||
super::api::call_api_with_tools_sync(caller, &prompts, &phases, None, None, &log)
|
super::api::call_api_with_tools_sync(caller, &prompts, &phases, None, &[], None, &log)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a model using an agent definition's configuration (multi-step).
|
/// Call a model using an agent definition's configuration (multi-step).
|
||||||
|
|
@ -34,7 +34,7 @@ pub(crate) fn call_for_def_multi(
|
||||||
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
||||||
log: &(dyn Fn(&str) + Sync),
|
log: &(dyn Fn(&str) + Sync),
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
super::api::call_api_with_tools_sync(&def.agent, prompts, phases, def.temperature, bail_fn, log)
|
super::api::call_api_with_tools_sync(&def.agent, prompts, phases, def.temperature, &def.tools, bail_fn, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue