diff --git a/docs/README.md b/docs/README.md index fc4069650..055d92e2c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,6 +7,7 @@ Welcome to the Agent Zero documentation hub. Whether you're getting started or d - **[Quickstart Guide](quickstart.md):** Get up and running in 5 minutes with Agent Zero. - **[Installation Guide](setup/installation.md):** Install scripts, updates, and advanced Docker setup (includes [How to Update](setup/installation.md#how-to-update-agent-zero)). +- **[A0 CLI Connector](guides/a0-cli-connector.md):** Install the terminal-native connector, connect it to Agent Zero, and copy a setup brief for another agent. - **[Self Update](guides/self-update.md):** How the in-app updater works (technical reference). - **[VPS Deployment](setup/vps-deployment.md):** Deploy Agent Zero on a remote server. - **[Development Setup](setup/dev-setup.md):** Set up a local development environment. @@ -14,6 +15,7 @@ Welcome to the Agent Zero documentation hub. Whether you're getting started or d ## User Guides - **[Usage Guide](guides/usage.md):** Comprehensive guide to Agent Zero's features and capabilities. +- **[A0 CLI Connector](guides/a0-cli-connector.md):** Terminal-first companion workflow for Agent Zero. - **[Projects Tutorial](guides/projects.md):** Learn to create isolated workspaces with dedicated context and memory. - **[API Integration](guides/api-integration.md):** Add external APIs without writing code. - **[MCP Setup](guides/mcp-setup.md):** Configure Model Context Protocol servers. @@ -69,6 +71,7 @@ Welcome to the Agent Zero documentation hub. Whether you're getting started or d - [Self Update (technical)](guides/self-update.md) - [VPS Deployment](setup/vps-deployment.md) - [Development Setup](setup/dev-setup.md) + - [A0 CLI Connector](guides/a0-cli-connector.md) - [User Guides](#user-guides) - [Usage Guide](guides/usage.md) @@ -91,6 +94,7 @@ Welcome to the Agent Zero documentation hub. Whether you're getting started or d - [Voice Interface](guides/usage.md#voice-interface) - [Memory Management](guides/usage.md#memory-management) - [Backup & Restore](guides/usage.md#backup--restore) + - [A0 CLI Connector](guides/a0-cli-connector.md) - [Projects Tutorial](guides/projects.md) - [API Integration](guides/api-integration.md) - [MCP Setup](guides/mcp-setup.md) diff --git a/docs/guides/a0-cli-connector.md b/docs/guides/a0-cli-connector.md new file mode 100644 index 000000000..be5166be3 --- /dev/null +++ b/docs/guides/a0-cli-connector.md @@ -0,0 +1,66 @@ +# A0 CLI Connector + +Agent Zero lives in Docker for a reason. That keeps it safer. The problem is that people see Docker and assume the agent can never really touch the code on their computer. + +A0 CLI is the answer to that. + +Agent Zero stays in Docker. A0 CLI installs on the host machine. That is what lets Agent Zero finally work on the real files on your real computer. + +For now, use the install commands below. + +## Quick Install + +**macOS / Linux:** +```bash +curl -LsSf https://raw.githubusercontent.com/agent0ai/a0-connector/main/install.sh | sh +``` + +**Windows (PowerShell):** +```powershell +irm https://raw.githubusercontent.com/agent0ai/a0-connector/main/install.ps1 | iex +``` + +**Manual fallback when uv is already installed or if URLs give 404:** +```bash +uv tool install git+https://github.com/agent0ai/a0-connector +``` + +Run these on the host machine, not inside the Agent Zero container. + +The installer uses `uv`, and `uv` will select or download a compatible Python if needed. + +## Open it and start working + +1. Make sure Agent Zero is already running. +2. Launch A0 CLI on the host machine: + +```bash +a0 +``` + +3. If Agent Zero is running on the same machine, A0 CLI will usually find it for you. +4. If Agent Zero is somewhere else, enter the exact web address or set `AGENT_ZERO_HOST` as env variable before launching `a0`. +5. Open or create a chat and confirm you can talk to Agent Zero from the host machine. + +> [!NOTE] +> Current Agent Zero builds starting from v1.9 include the builtin connector support that A0 CLI expects. If you see a connector-specific `404`, update Agent Zero first. + +## Give this to another agent + +If another agent is helping with setup, do not paste a whole checklist. Paste one line: + +```text +Set up the A0 CLI connector for Agent Zero on this machine using the a0-setup-cli Skill. +``` + +## Troubleshooting + +- **Nothing appears locally:** Enter the Agent Zero web address manually or export `AGENT_ZERO_HOST`. +- **You tried to install from inside Docker:** A0 CLI belongs on the host machine. Agent Zero stays in Docker. +- **Function keys do nothing:** Some terminals and IDEs capture function keys. Use `Ctrl+P`. +- **Connector route returns `404`:** Update Agent Zero to a build with builtin connector support. + +## Related links + +- [Quick Start](../quickstart.md) +- [Installation Guide](../setup/installation.md) diff --git a/docs/quickstart.md b/docs/quickstart.md index 93b48b181..4b3bbcd15 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -23,6 +23,34 @@ Follow the CLI prompts for port and authentication, complete onboarding, then op > [!NOTE] > For manual Docker Desktop setup, volume mapping, and platform-specific detail, see the [Installation Guide](setup/installation.md#manual-installation-advanced). +## Use Agent Zero on your real local files + +If you want Agent Zero to work on the actual files on your computer, this is the important part. + +Agent Zero stays in Docker for safety. The A0 CLI installs and runs on your host machine. That host-side CLI is what lets Agent Zero work on the real files on your real computer. + +**macOS / Linux:** +```bash +curl -LsSf https://raw.githubusercontent.com/agent0ai/a0-connector/main/install.sh | sh +``` + +**Windows (PowerShell):** +```powershell +irm https://raw.githubusercontent.com/agent0ai/a0-connector/main/install.ps1 | iex +``` + +Run those on the host machine, not inside the Agent Zero container. + +Then launch: + +```bash +a0 +``` + +Once `a0` connects, open or create a chat there. That is the path that lets Agent Zero stay in Docker while still working on real local files on your machine. + +For the full setup flow, manual fallback install paths, remote-host tips, and a copy-ready brief for another agent, see the [A0 CLI Connector guide](guides/a0-cli-connector.md). + ### Open the Web UI and configure your API key Open your browser and navigate to `http://localhost:`. The Web UI will show the onboarding banner. Click Start Onboarding to set your AI models and API key. diff --git a/docs/setup/installation.md b/docs/setup/installation.md index 25ed3e141..6ab094483 100644 --- a/docs/setup/installation.md +++ b/docs/setup/installation.md @@ -25,6 +25,9 @@ docker run -p 80:80 agent0ai/agent-zero Once the install completes, open the URL shown in your terminal to access the Web UI. Follow the prompts in the CLI to set your port and authentication, complete onboarding, add your API key, then continue to [Step 3: Configure Agent Zero](#step-3-configure-agent-zero). +> [!TIP] +> Prefer a terminal-native workflow too? Install the optional [A0 CLI Connector](../guides/a0-cli-connector.md) from GitHub, then run `a0` to connect to this Agent Zero instance from your terminal. + --- ## How to Update Agent Zero diff --git a/extensions/python/message_loop_prompts_after/_63_recall_relevant_skills.py b/extensions/python/message_loop_prompts_after/_63_recall_relevant_skills.py new file mode 100644 index 000000000..c4b2a45e8 --- /dev/null +++ b/extensions/python/message_loop_prompts_after/_63_recall_relevant_skills.py @@ -0,0 +1,39 @@ +from agent import LoopData +from helpers.extension import Extension +from helpers import skills as skills_helper + + +class RecallRelevantSkills(Extension): + async def execute(self, loop_data: LoopData = LoopData(), **kwargs): + if not self.agent or loop_data.iteration != 0: + return + + user_instruction = ( + loop_data.user_message.output_text() if loop_data.user_message else "" + ).strip() + if len(user_instruction) < 8: + return + + matches = skills_helper.search_skills( + user_instruction, + limit=6, + agent=self.agent, + ) + if not matches: + return + + lines: list[str] = [] + for skill in matches: + name = skill.name.strip().replace("\n", " ")[:100] + desc = (skill.description or "").replace("\n", " ").strip() + if len(desc) > 220: + desc = desc[:220].rstrip() + "…" + lines.append(f"- {name}: {desc}") + + if not lines: + return + + loop_data.extras_temporary["relevant_skills"] = self.agent.read_prompt( + "agent.system.skills.relevant.md", + skills="\n".join(lines), + ) diff --git a/helpers/skills.py b/helpers/skills.py index 4cd7028be..bf3b624d9 100644 --- a/helpers/skills.py +++ b/helpers/skills.py @@ -450,7 +450,11 @@ def search_skills( if not q: return [] - terms = [t for t in re.split(r"\s+", q) if t] + raw_terms = [t for t in re.split(r"\s+", q) if t] + terms = [ + t for t in raw_terms + if len(t) >= 3 or any(ch.isdigit() for ch in t) + ] or raw_terms candidates = list_skills(agent) scored: List[Tuple[int, Skill]] = [] @@ -458,8 +462,22 @@ def search_skills( name = s.name.lower() desc = (s.description or "").lower() tags = [t.lower() for t in s.tags] + triggers = [t.lower() for t in s.triggers] score = 0 + if q == name: + score += 10 + if any(q == trigger for trigger in triggers): + score += 9 + if q in name: + score += 6 + if q in desc: + score += 4 + if any(q in tag for tag in tags): + score += 3 + if any(q in trigger for trigger in triggers): + score += 8 + for term in terms: if term in name: score += 3 @@ -467,6 +485,8 @@ def search_skills( score += 2 if any(term in tag for tag in tags): score += 1 + if any(term in trigger for trigger in triggers): + score += 4 if score > 0: scored.append((score, s)) @@ -524,4 +544,3 @@ def validate_skill_md(skill_md_path: Path) -> List[str]: if not skill: return ["Unable to parse SKILL.md frontmatter"] return validate_skill(skill) - diff --git a/helpers/skills_cli.py b/helpers/skills_cli.py index 820d7e771..a510b111d 100644 --- a/helpers/skills_cli.py +++ b/helpers/skills_cli.py @@ -42,10 +42,19 @@ class Skill: def get_skills_dirs() -> List[Path]: """Get all skill directories""" base = Path(files.get_abs_path("usr", "skills")) - return [ + roots = [ + Path(files.get_abs_path("skills")), + base, base / "custom", base / "default", ] + seen: set[Path] = set() + ordered: List[Path] = [] + for root in roots: + if root not in seen: + seen.add(root) + ordered.append(root) + return ordered def parse_skill_file(skill_path: Path) -> Optional[Skill]: diff --git a/prompts/agent.system.skills.md b/prompts/agent.system.skills.md index 03d5fd814..6e74baed3 100644 --- a/prompts/agent.system.skills.md +++ b/prompts/agent.system.skills.md @@ -1,3 +1,4 @@ ## skills -use `skills_tool:list` to discover skills when specialized instructions may help +use `skills_tool:search` when the user's wording sounds like a task, trigger phrase, or keyword match for a skill +use `skills_tool:list` when you need a broader catalog view use `skills_tool:load` before following a skill diff --git a/prompts/agent.system.skills.relevant.md b/prompts/agent.system.skills.relevant.md new file mode 100644 index 000000000..05f73b8b3 --- /dev/null +++ b/prompts/agent.system.skills.relevant.md @@ -0,0 +1,5 @@ +# relevant skills +- the following skills matched the user's current request by lexical search, including trigger phrases +- use `skills_tool:load` to load one before following it + +{{skills}} diff --git a/prompts/agent.system.tool.skills.md b/prompts/agent.system.tool.skills.md index d3a1f54d4..19839d912 100644 --- a/prompts/agent.system.tool.skills.md +++ b/prompts/agent.system.tool.skills.md @@ -1,6 +1,7 @@ ### skills_tool use skills only when relevant workflow: +- `skills_tool:search`: find candidate skills by keywords or trigger phrases from the current task - `skills_tool:list`: discover available skills - `skills_tool:load`: load one skill by `skill_name` after loading a skill, follow its instructions and use referenced files or scripts with other tools @@ -8,11 +9,11 @@ reload a skill if its instructions are no longer in context example: ~~~json { - "thoughts": ["A skill may already encode the workflow I need."], - "headline": "Loading relevant skill", - "tool_name": "skills_tool:load", + "thoughts": ["The user's request sounds like a skill trigger phrase, so I should search first."], + "headline": "Searching for relevant skill", + "tool_name": "skills_tool:search", "tool_args": { - "skill_name": "playwright" + "query": "set up a0 cli connector" } } ~~~ diff --git a/skills/a0-setup-cli/SKILL.md b/skills/a0-setup-cli/SKILL.md new file mode 100644 index 000000000..54a5c2f88 --- /dev/null +++ b/skills/a0-setup-cli/SKILL.md @@ -0,0 +1,168 @@ +--- +name: a0-setup-cli +description: Guide the user through installing and connecting the A0 CLI on the host machine so Dockerized Agent Zero can work on real local files. Use when asked to install A0, set up the CLI connector, connect Agent Zero to local files, or troubleshoot host-vs-container setup confusion. +version: 1.0.0 +author: Agent Zero Team +tags: ["agent-zero", "a0", "cli", "connector", "docker", "setup", "local-files"] +trigger_patterns: + - "install a0" + - "install a0 cli" + - "set up a0 cli" + - "set up a0 cli connector" + - "connect a0 to agent zero" + - "connect agent zero to local files" + - "let agent zero work on my local files" + - "install the terminal connector" + - "help me set up the a0 cli connector" + - "install a0 connector" +--- + +# A0 CLI Host Setup + +Use this skill to guide the user through installing `a0` on their host machine and connecting it to Agent Zero. + +## Core Boundary + +- Agent Zero stays in Docker or its sandboxed runtime. +- `a0` installs and runs on the user's host machine. +- The whole point is to let Agent Zero work on the real files on the user's computer. + +## Response Flow + +### 1. Ask whether they already tried + +Start here: + +> Have you already tried installing `a0`? If so, what command did you run, where did you run it, and what happened? + +If they already tried, diagnose that attempt before repeating instructions. + +### 2. Stop container installs immediately + +If the user is inside the Agent Zero container, `/a0`, `docker exec`, or another sandbox shell, stop and say: + +> `a0` does not get installed inside the Agent Zero container. Exit to your normal host terminal first. Agent Zero stays in Docker; `a0` belongs on your machine. + +Do not keep giving install commands until they are back on the host. + +### 3. Identify the host OS only as needed + +If the platform is unclear, ask one short question: + +> Are you on macOS/Linux shell or Windows PowerShell on the host machine? + +Then use the matching installer. + +### 4. Use the installer-first flow + +Treat these public installer URLs as placeholders for now. Use them first, but be ready to switch to the manual `uv tool install` path if the raw GitHub URL is blocked, private, or unreachable. + +macOS / Linux: + +```bash +curl -LsSf https://raw.githubusercontent.com/agent0ai/a0-connector/main/install.sh | sh +``` + +Windows PowerShell: + +```powershell +irm https://raw.githubusercontent.com/agent0ai/a0-connector/main/install.ps1 | iex +``` + +The installer will install `uv` if needed, then run `uv tool install --upgrade ` for the CLI. + +### 5. Use the manual `uv tool install` fallback when needed + +If the placeholder installer URL is unavailable, switch to a manual `uv tool install` flow instead of stopping. + +Public Git fallback: + +```bash +uv tool install --upgrade git+https://github.com/agent0ai/a0-connector +``` + +Local checkout or internal mirror examples: + +```bash +uv tool install --upgrade /path/to/a0-connector +uv tool install --upgrade git+ssh://git.example.com/team/a0-connector.git +``` + +If they want to reuse the stock installer with a custom package source, explain that the installer honors `A0_PACKAGE_SPEC`. + +### 6. Tell them to run `a0` + +After install, the next step is always: + +```bash +a0 +``` + +If the command is not found yet, tell them to open a new terminal and run `a0` again. + +### 7. Explain how to connect + +Tell the user what to expect: + +- `a0` opens the host picker first. +- If Agent Zero is running locally, `a0` may discover it automatically. +- If not, the user can enter the Agent Zero web URL manually. +- `AGENT_ZERO_HOST` can prefill the target host without bypassing the picker. + +Example: + +```bash +export AGENT_ZERO_HOST=http://localhost:50001 +a0 +``` + +### 8. Define success clearly + +Successful setup looks like this: + +- `a0` starts on the host machine. +- It connects to the user's Agent Zero instance or reaches the login step. +- The user can open a chat from the terminal. +- Agent Zero can now act on real files on the host through the connector flow while Agent Zero itself still runs in Docker. + +## Troubleshooting + +- If the user says they installed inside Docker or shows `/a0` paths, redirect them to the host-machine install. +- If `a0` gets a connector `404`, explain that the running Agent Zero build likely does not include the builtin `_a0_connector` support yet and should be updated. +- If the browser UI works but `a0` does not, remind them the web UI can run without connector support but the CLI cannot. +- If Docker discovery does not find the instance, have them enter the exact Agent Zero URL or set `AGENT_ZERO_HOST`. + +## Example Requests And Responses + +### Example 1 + +User: "Help me set up the A0 CLI connector." + +Respond like this: + +1. Ask whether they already tried and whether they are on the host machine. +2. If the OS is unknown, ask whether they are in macOS/Linux shell or Windows PowerShell. +3. Give the matching installer command. +4. Tell them to run `a0`. +5. Explain what the host picker and successful connection should look like. + +### Example 2 + +User: "I'm inside the Agent Zero container. How do I install A0?" + +Respond like this: + +- Stop the flow. +- Explain that `a0` must be installed on the host, not in the container. +- Tell them to exit Docker, open a normal terminal on the machine, then continue with the host installer. + +### Example 3 + +User: "The raw GitHub installer URL is blocked on our network." + +Respond like this: + +- Say the public installer URL is only a placeholder path. +- Switch to a manual `uv tool install --upgrade ` flow. +- Offer examples for a local checkout, internal Git host, or the public Git URL if that one works. +- Then tell them to run `a0` and connect to Agent Zero. diff --git a/tools/skills_tool.py b/tools/skills_tool.py index fd462ddd1..b3607a45d 100644 --- a/tools/skills_tool.py +++ b/tools/skills_tool.py @@ -96,9 +96,9 @@ class SkillsTool(Tool): try: if method == "list": return Response(message=self._list(), break_loop=False) - # if method == "search": - # query = str(kwargs.get("query") or "").strip() - # return Response(message=self._search(query), break_loop=False) + if method == "search": + query = str(kwargs.get("query") or "").strip() + return Response(message=self._search(query), break_loop=False) if method == "load": skill_name = self._normalize_skill_name( str(kwargs.get("skill_name") or "") @@ -112,7 +112,7 @@ class SkillsTool(Tool): # ) return Response( - message="Error: missing/invalid 'method'. Supported: list, load.", + message="Error: missing/invalid 'method'. Supported: list, search, load.", break_loop=False, ) except ( @@ -144,30 +144,30 @@ class SkillsTool(Tool): lines.append("Tip: use skills_tool method=search or method=load for details.") return "\n".join(lines) - # def _search(self, query: str) -> str: - # if not query: - # return "Error: 'query' is required for method=search." + def _search(self, query: str) -> str: + if not query: + return "Error: 'query' is required for method=search." - # results = skills_helper.search_skills( - # query, - # limit=25, - # agent=self.agent, - # ) - # if not results: - # return f"No skills matched query: {query!r}" + results = skills_helper.search_skills( + query, + limit=25, + agent=self.agent, + ) + if not results: + return f"No skills matched query: {query!r}" - # lines: List[str] = [] - # lines.append(f"Skills matching {query!r} ({len(results)}):") - # for s in results: - # desc = (s.description or "").strip() - # if len(desc) > 200: - # desc = desc[:200].rstrip() + "…" - # lines.append(f"- {s.name}: {desc}") - # lines.append("") - # lines.append( - # "Tip: use skills_tool method=load skill_name= to load full instructions." - # ) - # return "\n".join(lines) + lines: List[str] = [] + lines.append(f"Skills matching {query!r} ({len(results)}):") + for s in results: + desc = (s.description or "").strip() + if len(desc) > 200: + desc = desc[:200].rstrip() + "…" + lines.append(f"- {s.name}: {desc}") + lines.append("") + lines.append( + "Tip: use skills_tool method=load skill_name= to load full instructions." + ) + return "\n".join(lines) def _load(self, skill_name: str) -> str: skill_name = self._normalize_skill_name(skill_name)