Use native skill discovery for all OpenResearch agents (#826)

* Enable shared native skills for ACP agents

* Exercise ACP native skill installation end to end

* Confirm ACP disconnect before testing skill restore

* Combine native skill discovery and remove duplicate catalog
This commit is contained in:
Daniel Kim
2026-10-29 15:24:01 -07:00
committed by GitHub
parent 5b74409aab
commit cbe099dfa9
4 changed files with 17 additions and 14 deletions
+2 -3
View File
@@ -121,9 +121,8 @@ currency signs, for example `\$10`.
## Skills
Available native OpenResearch skills:
{skill_names}
Native OpenResearch skills start with `orx-`. Prioritize these skills for
OpenResearch workflows.
Use the available OpenResearch skills whenever their descriptions match the user
task; the skills provide instructions on how to use relevant CLI commands and
+5 -1
View File
@@ -8370,7 +8370,11 @@ async fn set_chat_configuration(
.ok_or_else(|| not_found("project"))?;
let session_id = id.clone();
let (cwd, _) = tokio::task::spawn_blocking(move || {
local::opencode::ensure_playbook(&project, &session_id, None)
local::opencode::ensure_playbook(
&project,
&session_id,
Some(local::harness::acp::SESSION_SKILLS_DIR),
)
})
.await
.map_err(bad_request)?
+7 -1
View File
@@ -20,6 +20,8 @@ use crate::store::Store;
mod auth;
pub(crate) const SESSION_SKILLS_DIR: &str = ".agents/skills";
static DISCOVERY_SLOTS: tokio::sync::Semaphore = tokio::sync::Semaphore::const_new(2);
pub struct Acp(pub Definition);
@@ -71,6 +73,10 @@ impl Harness for Acp {
true
}
fn session_skills_dir(&self) -> Option<&'static str> {
Some(SESSION_SKILLS_DIR)
}
async fn detect_snapshot(&self) -> Option<HarnessInfo> {
Some(self.detection())
}
@@ -197,7 +203,7 @@ async fn run_turn(ctx: &mut TurnCtx, definition: &Definition) -> Result<()> {
let project = ctx.project.clone();
let session_id = ctx.session_id.clone();
let (cwd, _) = tokio::task::spawn_blocking(move || {
crate::local::opencode::ensure_playbook(&project, &session_id, None)
crate::local::opencode::ensure_playbook(&project, &session_id, Some(SESSION_SKILLS_DIR))
})
.await??;
let host = ctx.host.acp.clone();
+3 -9
View File
@@ -237,11 +237,6 @@ fn playbook_md(project: &LocalProject, state: &ProjectState) -> String {
{compute_default_source}; load **`orx-compute`** and read `orx compute instructions show` before configuring or launching"
);
let project_state = project_state_md(project, state);
let skill_names = super::agent_skills::skills(super::agent_skills::SkillSet::Local)
.iter()
.map(|skill| format!("- `{}`: {}", skill.name, skill.description))
.collect::<Vec<_>>()
.join("\n");
let template = SYSTEM_PROMPT
.split_once("-->\n\n")
.map(|(_, rest)| rest)
@@ -254,7 +249,6 @@ fn playbook_md(project: &LocalProject, state: &ProjectState) -> String {
.replace("{compute_bullet}", &compute_bullet)
.replace("{artifacts}", &artifacts)
.replace("{project_state}", &project_state)
.replace("{skill_names}", &skill_names)
}
/// Keep the files we drop into the checkout out of `git status` / accidental
@@ -1413,9 +1407,10 @@ mod tests {
assert!(md.contains("Use the available OpenResearch skills"));
assert!(md.contains("execute important user flows"));
assert!(!md.contains("orx skill <name>"));
// Native catalogs may abbreviate descriptions; preserve routing context here.
assert!(md.contains("Native OpenResearch skills start with `orx-`"));
assert!(md.contains("Load the relevant skill before acting"));
for skill in agent_skills::skills(SkillSet::Local) {
assert!(md.contains(&format!("- `{}`: {}", skill.name, skill.description)));
assert!(!md.contains(&format!("- `{}`:", skill.name)));
}
assert!(md.contains("orx-compute"));
assert!(md.contains("helping the user across the research process"));
@@ -1434,7 +1429,6 @@ mod tests {
let md = playbook_md(&project, &ProjectState::default());
assert!(md.contains("default target"));
assert!(md.contains("orx-compute"));
assert!(md.contains("orx-instances"));
assert!(!md.contains("## Cardinal rules"));
assert!(!md.contains("## Command index"));
assert!(!md.contains("## The auto-research loop"));