Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions core/continuum-core/src/cognition/llm_deliberation_faculty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3858,12 +3858,26 @@ mod tests {
// draft cost 238 tokens; trimming the DESCRIPTION to its contract (full
// accumulated CSS, replace-wholesale layer, delta meaning) recovered 47.
// What is left is the irreducible cost of one discoverable verb.
const AGENTIC_SURFACE_CEILING: u32 = 8650;
//
// 8650 β†’ 9400, stated plainly (2026-08-25): two NATIVE web verbs β€”
// `web/search` + `web/fetch` (+727 tokens even after trimming both
// DESCRIPTIONs to one line each; the rest is their irreducible param
// schemas). Web FORAGING is a deliberate capability-parity add (Joel: "make
// sure we have it" β€” the operator uses web lookup constantly on SWE/task
// work, and a native-call model like Ornith can ONLY emit calls for tools in
// its offered specs, so catalog-only web was unreachable to her hands). The
// surface already exceeded the 8192 tight-test window before this (8623 >
// 8192) β€” the budget trims VOLATILE context (recall/RAG) to fit and reserves
// specs up front, so this raises the reserved floor, it does not introduce a
// new overflow. Ornith serves at 166k where this ceiling is irrelevant; the
// tight-window LCD persona (which does not do web research) pays with less
// recall room, a conscious trade. If a third addition wants in, SHRINK first.
const AGENTIC_SURFACE_CEILING: u32 = 9400;
let surface =
faculty.describe_tool_tokens() as u32 + faculty.framing_floor_tokens();
assert!(
surface <= AGENTIC_SURFACE_CEILING,
"the agentic surface is now {surface} tokens (measured 8623, ceiling \
"the agentic surface is now {surface} tokens (measured 9350, ceiling \
{AGENTIC_SURFACE_CEILING}) β€” framing/tools grew. Shrink the surface (#333) \
or state plainly what was added and re-pin the ceiling"
);
Expand Down
7 changes: 3 additions & 4 deletions core/continuum-core/src/commands/web/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
use super::{web_fetch, WebFetchParams, WebFetchResult};

crate::action_command! {
/// Fetch a URL and READ its text β€” a doc page, API reference, article, or a result
/// `web/search` returned. Strips scripts/markup and returns clean, capped text you can
/// quote or reason over. This is how you actually read what you find online instead of
/// guessing from a snippet. Pair it with `web/search`: search to find the page, fetch to read it.
/// Read a web page's text (a doc, API reference, or a web/search result). Strips
/// markup, returns clean capped text; `filter` greps it to just what you need.
pub struct WebFetch;
name: "web/fetch",
access: AiSafe,
native: true, // her hands must be able to REACH the web (a native-call model can only emit calls in its offered specs); I forage constantly, so must she β€” direct SWE/task score lever
params: WebFetchParams,
output: WebFetchResult,
run(_this, _ctx, p) => { web_fetch(p).await }
Expand Down
29 changes: 17 additions & 12 deletions core/continuum-core/src/commands/web/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
use super::{web_search, WebSearchParams, WebSearchResult};

crate::action_command! {
/// Search the WEB for current information beyond your memory β€” docs, articles,
/// papers, news, how-tos. Returns ranked results (title, url, snippet) you can
/// cite or read further. Pick a backend with `adapter`: "brave" (best β€” needs a
/// free BRAVE_API_KEY) or "duckduckgo" (keyless, works with no setup). Omit
/// `adapter` to auto-use the best available β€” so this works even with no API
/// key configured. Use it to forage for what you don't know yet.
/// Search the web for current info beyond your memory (docs, APIs, errors,
/// how-tos). Returns ranked results (title, url, snippet) to read with web/fetch.
pub struct WebSearch;
name: "web/search",
access: AiSafe,
native: true, // her hands must be able to REACH the web (a native-call model can only emit calls in its offered specs); I forage constantly, so must she β€” direct SWE/task score lever
params: WebSearchParams,
output: WebSearchResult,
run(_this, _ctx, p) => { web_search(p).await }
Expand All @@ -22,14 +19,22 @@ mod tests {
use super::*;
use crate::sdk_codegen::ActionCommand;

// what this catches: the wire name + a description that names BOTH adapters and
// the keyless guarantee β€” the persona is offered "web/search" with guidance that
// it works without a key. Name is the routing key; a drift unwires the hand.
// what this catches: the wire name (routing key β€” a drift unwires the hand) and
// that the description is the CONCISE model-facing line it became when web went
// NATIVE (2026-08-25): the adapter/keyless detail moved OUT of DESCRIPTION β€” which
// rides the token-budgeted native surface β€” and INTO the `adapter` param doc, so
// the surface stayed under its ceiling. The description must still say what the
// tool DOES (search the web) and point at its partner (web/fetch); the
// adapter/keyless guidance is asserted on the PARAM, its new home.
#[test]
fn name_and_description() {
assert_eq!(WebSearch::NAME, "web/search");
assert!(WebSearch::DESCRIPTION.contains("brave"));
assert!(WebSearch::DESCRIPTION.contains("duckduckgo"));
assert!(WebSearch::DESCRIPTION.contains("no API key"));
let d = WebSearch::DESCRIPTION.to_lowercase();
assert!(d.contains("search") && d.contains("web"), "names what it does: {}", WebSearch::DESCRIPTION);
assert!(d.contains("web/fetch"), "points at its read partner");
// The adapter/keyless detail now lives on the param, not the surface-costed DESCRIPTION.
let schema = serde_json::to_string(&schemars::schema_for!(WebSearchParams)).unwrap_or_default();
assert!(schema.contains("brave") && schema.contains("duckduckgo"),
"adapter guidance lives in the param schema now");
}
}
Loading