#!/usr/bin/env -S uv run # /// script # dependencies = [] # /// """make_adw — generate a new one-shot ADW script from agents in the config. Usage: uv run /scripts/make_adw.py --name review_docs --agents scout,builder Each named agent becomes one agent phase, chained by envelope. Starter agents map to their concrete output types; unknown agents get GenericOutput (define a concrete type in adw_modules/data_types.py and swap it in). """ import argparse import sys from pathlib import Path OUTPUT_TYPES = {"planner": "PlanOutput", "builder": "BuildOutput", "scout": "ScoutOutput", "reviewer": "ReviewOutput", "documenter": "DocumentOutput"} HEADER = '''#!/usr/bin/env -S uv run # /// script # dependencies = ["pydantic", "python-dotenv", "pyyaml"] # /// """ADW {title} — generated by make_adw. Usage: uv run adws/adw_{name}.py "" [--config adws/adw_sssf_config/sssf.config.yaml] [--adw-id a1b2c3d4] Phases: engineer(request) -> {chain} """ import argparse import sys from adw_modules import agents, gates, session, utils from adw_modules.data_types import AgentCall, PhaseParams, {imports} REQUIRED_AGENTS = {agents_list} def main(prompt: str, config: str = "adws/adw_sssf_config/sssf.config.yaml", adw_id: str | None = None) -> int: cfg = agents.load_config(config) agents.validate(cfg, REQUIRED_AGENTS) run = session.ensure(cfg, adw_id) with run.phase(PhaseParams(name="request", kind="engineer", owner=run.engineer, description="Capture the incoming ask")) as ph: ph.log(input=prompt) previous = None {phases} return 0 if run.succeeded else 1 if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("prompt", help="inline text or a path to a prompt file") parser.add_argument("--config", default="adws/adw_sssf_config/sssf.config.yaml") parser.add_argument("--adw-id", default=None, help="join or pin an existing session") args = parser.parse_args() sys.exit(main(utils.resolve_prompt(args.prompt), args.config, args.adw_id)) ''' PHASE = ''' # TODO: replace this description — say what THIS phase does and why. with run.phase(PhaseParams(name="{name}", kind="agent", owner="{agent}", description="Run {agent} over the request and hand its envelope on")) as ph: previous = ph.call(AgentCall(output_type={output_type}, prompt=prompt, previous=previous, gates=[gates.artifacts_exist])) ''' def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--name", required=True, help="snake_case adw name") parser.add_argument("--agents", required=True, help="comma-separated agent names, in order") parser.add_argument("--force", action="store_true") args = parser.parse_args() agent_names = [a.strip() for a in args.agents.split(",") if a.strip()] if not agent_names: print("no agents given") return 1 types = [OUTPUT_TYPES.get(a, "GenericOutput") for a in agent_names] seen: dict[str, int] = {} phases = [] for agent, output_type in zip(agent_names, types): seen[agent] = seen.get(agent, 0) + 1 phase_name = agent if seen[agent] == 1 else f"{agent}_{seen[agent]}" phases.append(PHASE.format(name=phase_name, agent=agent, output_type=output_type)) body = HEADER.format( title=args.name.replace("_", " ").title(), name=args.name, chain=" -> ".join(agent_names), imports=", ".join(sorted(set(types))), agents_list=repr(sorted(set(agent_names))), phases="\n".join(phases), ) dest = Path.cwd() / "adws" / f"adw_{args.name}.py" if dest.exists() and not args.force: print(f"{dest} already exists — use --force to overwrite") return 1 dest.parent.mkdir(parents=True, exist_ok=True) dest.write_text(body) print(f"wrote {dest}") print("next: replace each phase description — a generated one says nothing, " "and the description is the only intent the trace ever shows") print(f"run: uv run adws/adw_{args.name}.py \"your request\"") return 0 if __name__ == "__main__": sys.exit(main())