Add subagent prompts and implement company workflow orchestration

- Introduced prompts for various subagent roles: architecture reviewer, code quality reviewer, documentation maintainer, implementation team, testing team, and security reviewer.
- Implemented the auto-subagent orchestration in `auto.rs` to manage inline and background reviews.
- Created a division structure in `division.rs` to define roles and responsibilities for each subagent.
- Developed a company workflow orchestrator in `company.rs` to run the complete division pipeline, consolidating findings and generating executive summaries.
- Added logic to determine whether to run a full or quick pipeline based on request complexity.
This commit is contained in:
asepharyana
2026-07-13 05:23:38 +07:00
parent 2856dd78b8
commit a6eed9e574
21 changed files with 1577 additions and 85 deletions
+1
View File
@@ -169,6 +169,7 @@ pub fn all_tools() -> Vec<Box<dyn Tool>> {
Box::new(super::tool::plan::PlanReady),
Box::new(super::tool::workflow::WorkflowRun),
Box::new(super::tool::workflow::NoteFinding),
Box::new(super::tool::workflow::CompanyPipeline),
Box::new(super::tool::spawn::SpawnAgents),
Box::new(super::tool::spawn::SpawnPipeline),
Box::new(super::tool::memory::remember::Remember),
+4 -6
View File
@@ -91,12 +91,11 @@ impl Tool for SpawnAgents {
use std::sync::{Arc, Mutex};
let live: Option<crate::app::workflow::engine::LiveStateFn> = _ctx.turn_events.as_ref().map(|turn_events| {
let turn_events = turn_events.clone();
let f: crate::app::workflow::engine::LiveStateFn = Arc::new(move |agent_id: String, status| {
let name = agent_id.chars().take(30).collect::<String>();
let f: crate::app::workflow::engine::LiveStateFn = Arc::new(move |agent_id: String, agent_name: String, status| {
if let Ok(mut q) = turn_events.lock() {
q.push_back(crate::app::state::runtime::TurnEvent::WorkflowAgentUpdate {
agent_id,
agent_name: name,
agent_name,
status,
});
}
@@ -182,12 +181,11 @@ impl Tool for SpawnPipeline {
use std::sync::{Arc, Mutex};
let live: Option<crate::app::workflow::engine::LiveStateFn> = _ctx.turn_events.as_ref().map(|turn_events| {
let turn_events = turn_events.clone();
let f: crate::app::workflow::engine::LiveStateFn = Arc::new(move |agent_id: String, status| {
let name = agent_id.chars().take(30).collect::<String>();
let f: crate::app::workflow::engine::LiveStateFn = Arc::new(move |agent_id: String, agent_name: String, status| {
if let Ok(mut q) = turn_events.lock() {
q.push_back(crate::app::state::runtime::TurnEvent::WorkflowAgentUpdate {
agent_id,
agent_name: name,
agent_name,
status,
});
}
+68
View File
@@ -138,3 +138,71 @@ impl Tool for NoteFinding {
Ok(format!("finding recorded: {}", text.chars().take(80).collect::<String>()))
}
}
/// Tool that delegates work to the company-style division pipeline.
///
/// The main agent (CEO) calls this tool to pass a user request through the
/// full company organization: Strategy → Engineering → Quality → Security
/// → Documentation. Returns an executive summary.
///
/// Use this for any complex or multi-step task. For simple tasks, handle
/// inline or use the quick variant.
pub struct CompanyPipeline;
impl Tool for CompanyPipeline {
fn name(&self) -> &'static str {
"company_pipeline"
}
fn description(&self) -> &'static str {
"Delegate a task to the full company division pipeline: Strategy (plan+diagrams) → Engineering (implement) → Quality (review+test) → Security (audit) → Documentation (docs). Use this for ALL non-trivial tasks instead of doing them yourself. The pipeline returns an executive summary."
}
fn parameters(&self) -> Value {
json!({
"type": "object",
"properties": {
"request": {
"type": "string",
"description": "The task description to delegate to the company pipeline"
},
"mode": {
"type": "string",
"enum": ["full", "quick"],
"description": "Pipeline mode: 'full' (5 divisions) for complex tasks, 'quick' (3 divisions: Strategy→Engineering→Quality) for simpler tasks",
"default": "full"
}
},
"required": ["request"]
})
}
fn run(&self, _ctx: &ToolCtx, args: &Value) -> Result<String> {
let request = args.get("request")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow!("missing required argument: request"))?;
let mode = args.get("mode")
.and_then(|v| v.as_str())
.unwrap_or("full");
match mode {
"quick" => {
crate::app::workflow::company::run_company_pipeline_quick(
request,
&_ctx.session_dir,
&_ctx.workspaces,
_ctx.turn_events.as_ref(),
)
}
_ => {
crate::app::workflow::company::run_company_pipeline(
request,
&_ctx.session_dir,
&_ctx.workspaces,
_ctx.turn_events.as_ref(),
)
}
}
}
}