Try this first
Send agent.py to a colleague and ask them to run it.
Count what goes wrong: no anthropic installed, no API key, a Python version mismatch, hard
coded paths, and it starts in whatever folder they happened to be in.
The five things
1. Dependencies, declared.
# pyproject.toml
[project]
name = "rover"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = ["anthropic>=0.40", "mcp>=1.0"]
[project.scripts]
rover = "rover.cli:main"
requires-python earns its place — anthropic[mcp] needs 3.10, and a clear error at install
time beats a confusing one at import.
2. Configuration, not constants.
Everything a user might change comes from the environment, with a sensible default:
import os
LLM_SPEC = os.environ.get("ROVER_LLM", "ollama:gemma4")
MAX_TURNS = int(os.environ.get("ROVER_MAX_TURNS", "25"))
WORKDIR = Path(os.environ.get("ROVER_WORKDIR", ".")).resolve()
And fail early with a message a person can act on:
if not os.environ.get("ANTHROPIC_API_KEY"):
raise SystemExit(
"ANTHROPIC_API_KEY is not set.\n"
"Get a key from the Anthropic console and run:\n"
' export ANTHROPIC_API_KEY="sk-..."'
)
Compare that with a stack trace ending in AuthenticationError. Same information, ten seconds
versus ten minutes.
3. The working directory is a decision, not an accident.
safe_path from Lesson 3.5 uses Path.cwd(). On your machine that is your project. On
someone else’s it is wherever they were standing — possibly their home folder, which makes
your boundary meaningless.
Make it explicit, and say what it is:
print(f"Rover is working in {WORKDIR}. It cannot read or write outside this folder.")
4. Errors that are not tracebacks.
try:
main()
except AuthError: # your provider's own exception class
raise SystemExit("Your API key was rejected. Check the key for your provider.")
except RateLimitError: # same
raise SystemExit("Rate limited. Wait a minute and try again.")
except KeyboardInterrupt:
raise SystemExit("\nStopped.")
Three lines each, and your tool stops looking broken when it is merely being told no.
5. A README that says what it touches.
Same list as Lesson 5.7, for the same reason:
- What it does
- Which folder it can read and write
- Whether it can run shell commands
- What it sends to the API, and what that costs
Those two bold lines are what a careful person looks for before running someone else’s agent.
Yours should have them, because you now know why they matter.
What you are actually shipping
Worth being plain about, because it changes how you write the README.
You are shipping something that reads a person’s files, may run commands on their machine, and
sends what it finds to an API. That is a lot to hand someone in exchange for a pip install.
Everything above is how you make that trade legible to them. It is not paperwork. It is the
difference between a tool a colleague will run and one they will read and quietly not run.
Config from the environment, an explicit working directory, errors that suggest a fix, and a
README that says what it touches.
Try this before the final project
Package Rover and install it in a clean virtual environment, in a different folder, as if you
were someone else.
Everything that confuses you in the first two minutes is what your README is missing.