Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -618,15 +618,17 @@ uv run ruff check . && uv run ruff format .

### PEP 723 Script Metadata (Required for `uv run` support)

Every example file must include PEP 723 inline script metadata at the top for standalone execution with `uv run`:
Every example file must include PEP 723 inline script metadata at the top for
standalone execution with `uv run` — this includes **every** standalone script
in an example directory (registration/provisioning helpers, test harnesses,
one-off utilities), not just the primary agent entrypoint. Bare `python foo.py`
assumes the SDK is already installed; document `uv run foo.py` in the README so
the script runs against a fetched-on-the-fly SDK. Metadata:

```python
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[<extra>]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[<extra>]>=1.2.0,<2.0.0"]
# ///
"""
Brief description of what this example does.
Expand All @@ -638,16 +640,53 @@ Run with:

Replace `<extra>` with the appropriate framework extra (e.g., `langgraph`, `anthropic`, `crewai`, `claude-sdk`, `pydantic-ai`, `parlant`).

**Depend on the published PyPI `band-sdk`, pinned `>=1.2.0,<2.0.0`** — not a
`[tool.uv.sources]` git override. `uv run` then fetches a released wheel instead
of building the default branch HEAD (reproducible, no git needed). The **only**
exception: an example whose extra is not yet published on PyPI (a brand-new
adapter) may keep a git source until the next release exposes the extra — leave
a one-line comment saying so, and flip it to the pinned PyPI form once released.

### Other Requirements

- Use `load_agent_config("agent_name")` for credentials, NOT direct `os.environ.get()`
and NOT a hand-rolled YAML loader. `band.config.load_agent_config()` already
validates a missing file / empty values / required fields and understands both
the keyed (`planner:`/`reviewer:`) and flat single-agent formats — reuse it.
- Always load and validate `BAND_WS_URL` and `BAND_REST_URL` with `ValueError`
- **A helper script must read the same config source as the stack it supports.**
If the runtime (e.g. Docker Compose) reads `.env` for `BAND_REST_URL`, the
companion scripts must `load_dotenv()` the same `.env` — otherwise they
silently target a *different* platform (the default `app.band.ai`) than the
containers, and register/probe agents the stack can't see.
- Use `raise ValueError(...)` for missing required config, NOT `logger.error()` + `sys.exit()`
- Use single sys.path line: `sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))`
- Never hardcode UUIDs in docstrings - reference `agent_config.yaml` instead
- All `async def main()` functions must have `-> None` return type hint
- Always include `from __future__ import annotations` as first import

### Provisioning / setup scripts (create-agents, register-*, bootstrap)

Scripts that create remote resources (agents, rooms) or generate credential
files have failure modes plain examples don't. Follow these:

- **Persist created resource ids immediately, append-only.** Write each id to a
cleanup ledger the moment the resource exists — before the next create or any
file write can fail. Writing all ids once at the end orphans everything already
created if a later step throws; overwriting the ledger on a re-run loses the
*previous* run's ids. Both leak paid/limited resources.
- **Refuse to clobber existing credentials without an explicit `FORCE`.** A
re-run that silently overwrites `agent_config.yaml` orphans the agents it
referenced. Fail with a message pointing at the cleanup ledger.
- **Guard file writes against the stale bind-mount directory.** Docker
auto-creates a *missing* bind-mount source as an empty **directory**. Check
`path.is_dir()` / `path.exists()`, NOT `path.is_file()` (which is `False` for a
directory and lets the work run, then crashes at `write_text` with
`IsADirectoryError`). Do this check **before** any irreversible step (e.g.
registering agents), so you never create resources you then can't record.
- **Keep `main()` thin.** Extract persistence (config/ledger writes) and the
user-facing summary into small named helpers — easier to read and to test.

## Documentation Testing (markdown snippets)

Tracked `.md` files (except `examples/`) run in CI as tests via `pytest-markdown-docs`
Expand Down
5 changes: 1 addition & 4 deletions examples/20-questions-arena/guesser_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[langgraph]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[langgraph]>=1.2.0,<2.0.0"]
# ///
"""
Guesser agent for the 20 Questions Arena game.
Expand Down
5 changes: 1 addition & 4 deletions examples/20-questions-arena/start_game.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[langgraph]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[langgraph]>=1.2.0,<2.0.0"]
# ///
"""Start a 20 Questions Arena game as a user by creating a room, adding all agents, and sending a message.

Expand Down
5 changes: 1 addition & 4 deletions examples/20-questions-arena/thinker_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[langgraph]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[langgraph]>=1.2.0,<2.0.0"]
# ///
"""
Thinker agent for the 20 Questions Arena game.
Expand Down
5 changes: 1 addition & 4 deletions examples/a2a_bridge/01_basic_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[a2a]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[a2a]>=1.2.0,<2.0.0"]
# ///
"""
Basic A2A adapter example.
Expand Down
5 changes: 1 addition & 4 deletions examples/a2a_bridge/02_with_auth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[a2a]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[a2a]>=1.2.0,<2.0.0"]
# ///
"""
A2A adapter with authentication example.
Expand Down
5 changes: 1 addition & 4 deletions examples/a2a_gateway/01_basic_gateway.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[a2a_gateway]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[a2a_gateway]>=1.2.0,<2.0.0"]
# ///
"""
Basic A2A Gateway adapter example.
Expand Down
5 changes: 1 addition & 4 deletions examples/a2a_gateway/02_with_demo_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[a2a_gateway_demo]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[a2a_gateway_demo]>=1.2.0,<2.0.0"]
# ///
"""
Run A2A Gateway with Demo Orchestrator Agent.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/clients/bridge_architecture.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
ACP Bridge Architecture example.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/clients/copilot.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
GitHub Copilot CLI ACP Client - Use GitHub Copilot from Band.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/clients/cursor.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
Cursor ACP Client - Use Cursor's AI agent from Band.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/clients/generic.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
ACP Client example - Use a remote ACP agent from Band.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/clients/rich_streaming.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
ACP Client with rich streaming - Thoughts, tool calls, and plans.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/copilot_docker/colocated/client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]", "pydantic-settings", "python-dotenv"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
Host-side Band SDK client for the colocated Copilot Docker example.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/copilot_docker/compose/client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]", "pydantic-settings"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git"}
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
Host-side Band SDK client for the Copilot Docker Compose example.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/copilot_sandbox/client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
GitHub Copilot in a Docker sandbox (sbx), driven by Band over stdio.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/servers/basic.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
Basic ACP Server example - Band as an ACP agent.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/servers/jetbrains.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
JetBrains ACP Server - Use Band as an ACP agent in JetBrains IDEs.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/servers/push_notifications.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
ACP Server with push notifications - Real-time activity from Band peers.
Expand Down
5 changes: 1 addition & 4 deletions examples/acp/servers/routing.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[acp]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[acp]>=1.2.0,<2.0.0"]
# ///
"""
ACP Server with routing - Target specific peers via slash commands or modes.
Expand Down
5 changes: 1 addition & 4 deletions examples/agentcore/agentcore_llm_server.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "band-sdk[anthropic]",
# "band-sdk[anthropic]>=1.2.0,<2.0.0",
# "fastapi>=0.110",
# "uvicorn>=0.29",
# ]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# ///
"""AgentCore container that runs the Band SDK per invocation.

Expand Down
5 changes: 1 addition & 4 deletions examples/agentcore/verify_deployment.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk>=1.2.0,<2.0.0"]
# ///
"""Post-deployment smoke check for the AgentCore demo in this folder.

Expand Down
5 changes: 1 addition & 4 deletions examples/agno/01_basic_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[agno]", "anthropic>=0.75.0"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[agno]>=1.2.0,<2.0.0", "anthropic>=0.75.0"]
# ///
"""
Basic Agno agent example.
Expand Down
5 changes: 1 addition & 4 deletions examples/agno/02_tool_reporting.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[agno]", "anthropic>=0.75.0"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[agno]>=1.2.0,<2.0.0", "anthropic>=0.75.0"]
# ///
"""
Agno agent with tool-execution reporting.
Expand Down
5 changes: 1 addition & 4 deletions examples/agno/03_tom_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[agno]", "anthropic>=0.75.0"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[agno]>=1.2.0,<2.0.0", "anthropic>=0.75.0"]
# ///
"""
Tom the cat agent — tries to catch Jerry!
Expand Down
5 changes: 1 addition & 4 deletions examples/agno/04_jerry_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[agno]", "anthropic>=0.75.0"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[agno]>=1.2.0,<2.0.0", "anthropic>=0.75.0"]
# ///
"""
Jerry the mouse agent — outsmarts Tom!
Expand Down
5 changes: 1 addition & 4 deletions examples/agno/05_memory_secretary.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[agno]", "anthropic>=0.75.0"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[agno]>=1.2.0,<2.0.0", "anthropic>=0.75.0"]
# ///
"""
Agno agent with Band memory tools enabled.
Expand Down
5 changes: 1 addition & 4 deletions examples/agno/06_agno_db_history.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[agno]", "anthropic>=0.75.0"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[agno]>=1.2.0,<2.0.0", "anthropic>=0.75.0"]
# ///
"""
Agno-owned conversation history with a database.
Expand Down
5 changes: 1 addition & 4 deletions examples/anthropic/01_basic_agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[anthropic]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[anthropic]>=1.2.0,<2.0.0"]
# ///
"""
Basic Anthropic SDK agent example.
Expand Down
5 changes: 1 addition & 4 deletions examples/anthropic/02_custom_instructions.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["band-sdk[anthropic]"]
#
# [tool.uv.sources]
# band-sdk = { git = "https://github.com/band-ai/band-sdk-python.git" }
# dependencies = ["band-sdk[anthropic]>=1.2.0,<2.0.0"]
# ///
"""
Agent with custom system prompt instructions.
Expand Down
Loading
Loading