feat: add memory tool (#10637)

Add a tool for memory to retrieve a full memory based on the memory ID
This commit is contained in:
jif-oai
2026-02-05 16:16:31 +00:00
committed by GitHub
parent fe1cbd0f38
commit 41f3b1ba0b
7 changed files with 232 additions and 0 deletions

View File

@@ -31,6 +31,7 @@ pub(crate) struct ToolsConfig {
pub web_search_mode: Option<WebSearchMode>,
pub collab_tools: bool,
pub collaboration_modes_tools: bool,
pub memory_tools: bool,
pub request_rule_enabled: bool,
pub experimental_supported_tools: Vec<String>,
}
@@ -51,6 +52,7 @@ impl ToolsConfig {
let include_apply_patch_tool = features.enabled(Feature::ApplyPatchFreeform);
let include_collab_tools = features.enabled(Feature::Collab);
let include_collaboration_modes_tools = features.enabled(Feature::CollaborationModes);
let include_memory_tools = features.enabled(Feature::MemoryTool);
let request_rule_enabled = features.enabled(Feature::RequestRule);
let shell_type = if !features.enabled(Feature::ShellTool) {
@@ -84,6 +86,7 @@ impl ToolsConfig {
web_search_mode: *web_search_mode,
collab_tools: include_collab_tools,
collaboration_modes_tools: include_collaboration_modes_tools,
memory_tools: include_memory_tools,
request_rule_enabled,
experimental_supported_tools: model_info.experimental_supported_tools.clone(),
}
@@ -634,6 +637,28 @@ fn create_request_user_input_tool() -> ToolSpec {
})
}
fn create_get_memory_tool() -> ToolSpec {
let properties = BTreeMap::from([(
"memory_id".to_string(),
JsonSchema::String {
description: Some(
"Memory ID to fetch. Uses the thread ID as the memory identifier.".to_string(),
),
},
)]);
ToolSpec::Function(ResponsesApiTool {
name: "get_memory".to_string(),
description: "Loads the full stored memory payload for a memory_id.".to_string(),
strict: false,
parameters: JsonSchema::Object {
properties,
required: Some(vec!["memory_id".to_string()]),
additional_properties: Some(false.into()),
},
})
}
fn create_close_agent_tool() -> ToolSpec {
let mut properties = BTreeMap::new();
properties.insert(
@@ -1228,6 +1253,7 @@ pub(crate) fn build_specs(
use crate::tools::handlers::ApplyPatchHandler;
use crate::tools::handlers::CollabHandler;
use crate::tools::handlers::DynamicToolHandler;
use crate::tools::handlers::GetMemoryHandler;
use crate::tools::handlers::GrepFilesHandler;
use crate::tools::handlers::ListDirHandler;
use crate::tools::handlers::McpHandler;
@@ -1249,6 +1275,7 @@ pub(crate) fn build_specs(
let plan_handler = Arc::new(PlanHandler);
let apply_patch_handler = Arc::new(ApplyPatchHandler);
let dynamic_tool_handler = Arc::new(DynamicToolHandler);
let get_memory_handler = Arc::new(GetMemoryHandler);
let view_image_handler = Arc::new(ViewImageHandler);
let mcp_handler = Arc::new(McpHandler);
let mcp_resource_handler = Arc::new(McpResourceHandler);
@@ -1308,6 +1335,11 @@ pub(crate) fn build_specs(
builder.register_handler("request_user_input", request_user_input_handler);
}
if config.memory_tools {
builder.push_spec(create_get_memory_tool());
builder.register_handler("get_memory", get_memory_handler);
}
if let Some(apply_patch_tool_type) = &config.apply_patch_tool_type {
match apply_patch_tool_type {
ApplyPatchToolType::Freeform => {
@@ -1669,6 +1701,33 @@ mod tests {
assert_contains_tool_names(&tools, &["request_user_input"]);
}
#[test]
fn get_memory_requires_memory_tool_feature() {
let config = test_config();
let model_info = ModelsManager::construct_model_info_offline("gpt-5-codex", &config);
let mut features = Features::with_defaults();
features.disable(Feature::MemoryTool);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
web_search_mode: Some(WebSearchMode::Cached),
});
let (tools, _) = build_specs(&tools_config, None, &[]).build();
assert!(
!tools.iter().any(|t| t.spec.name() == "get_memory"),
"get_memory should be disabled when memory_tool feature is off"
);
features.enable(Feature::MemoryTool);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
web_search_mode: Some(WebSearchMode::Cached),
});
let (tools, _) = build_specs(&tools_config, None, &[]).build();
assert_contains_tool_names(&tools, &["get_memory"]);
}
fn assert_model_tools(
model_slug: &str,
features: &Features,