Skip to content

Add AGENTS.md - #256

Open
brandomr wants to merge 3 commits into
devfrom
add-agents-md
Open

Add AGENTS.md#256
brandomr wants to merge 3 commits into
devfrom
add-agents-md

Conversation

@brandomr

Copy link
Copy Markdown
Contributor

Notes from working on this repo and building a context against it. Aimed at the things that cost time to discover and are not visible from reading the source.

What's covered

Running from a checkout. The prebuilt frontend ships in the wheel as a build artifact and is gitignored, so an editable install serves no UI until you either run make init or copy the assets out of an installed wheel. Also: uv run re-syncs from uv.lock and silently replaces an editable beaker-notebook with the locked PyPI version, so a checkout under test appears to have no effect until you call the venv binary directly.

Where credentials actually come from. Config resolution order, and the fact that a blank or missing config does not mean no key: provider classes fall back to environment variables, so OPENAI_API_KEY and friends will satisfy an otherwise unconfigured install. Relevant if you are ever trying to reproduce a first-run experience, which needs an environment with none of them set.

Contexts. Entry-point discovery and why moving a context needs a reinstall, WEIGHT deciding which context a session opens on, the two REST endpoints worth asserting against in tests, and procedures being Jinja templates.

Skills. The skills.json and skills/ conventions, global roots attaching to every context, the trailing slash on remote URLs being load bearing, and skills failing to load silently (#254).

Recording a demo video. The longest section, because Beaker is awkward to record and each pitfall produces output that looks fine until you watch it:

  • Waiting for the transcript to stop changing fires mid-turn, because turns go quiet while a tool call runs. Six prompts stacked before any answer in my first attempt. Gate on the Agent Running block instead.
  • keyboard.press("End") scrolls the focused element, which after typing is the query textarea, so the transcript never moves and figures render off screen.
  • The agent saves a figure and loads it back to describe it, which 404s on any model without image input. One instruction in the prompt avoids it, and counting img[src^='data:image'] verifies plotting actually worked.

Plus ffmpeg recipes, and the note that GitHub strips <video> from markdown so a README needs a GIF.

Checked

Every claim verified against current dev rather than written from memory: config wording in cli/config.py, WEIGHT = 10 on DefaultContext, app/ui in the wheel artifacts, asyncio_mode = auto, the _get_skill_search_roots patching in the skill tests, and the swallowed exception in discover_integrations.

Happy to cut anything that reads as too specific to my use case.

brandomr and others added 2 commits July 22, 2026 15:26
Notes from working on this repository and building a context against it.
Covers the things that cost time to discover and are not visible from the
source: where configuration and credentials actually resolve from, how
context and skill discovery behave, and how to record a demo video of a
Beaker session.

The video section is the longest because Beaker is genuinely awkward to
record, and each of the three pitfalls produces output that looks fine until
you watch it. Waiting for the transcript to stop changing fires mid turn and
stacks prompts on top of each other; End scrolls the query textarea rather
than the transcript, so figures render off screen; and the agent will save a
plot and load it back to describe it, which 404s on any model without image
input.

Every claim was checked against the current dev branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz
The credentials section was the weak point. The first version blamed shell
environment variables for keys surviving isolation, which is only one of
three mechanisms and not the one that actually bit. Now documents all
three, each verified against the code and reproduced live:

- Config.from_config_file loads a .env located by dotenv.find_dotenv(),
  which walks up from lib/config.py's own location. A .env anywhere above
  the install location injects variables into every run from that
  environment, regardless of cwd or $HOME. Reproduced: locate_envfile()
  from a venv three directories deep resolved to a repo-root .env.
- Provider classes fall back to environment variables.
- BeakerKernelManager sets the kernel's HOME and cwd to the agent user's
  passwd-database home, discarding the server's environment, so wrapping
  the server process isolates nothing that matters.

Corrections to the first version: the cp -R recipe nested ui/ui on a second
run (now rm -rf first); the skill search roots under "the working
directory" and "the home directory" usually coincide because the kernel's
cwd is set to the home; WEIGHT has no tie-break beyond dict order, so
strictly-lowest is the requirement; the flicker claim about the Agent
Running block is now phrased as the race it guards against rather than an
observed behavior.

New sections: version skew for downstream context authors (the
SkillIntegrationProvider positional-argument meaning changed between 2.0.9
and this branch, silently), inspecting a live session through the REST
endpoints, and stable Playwright selectors. GIF guidance now says to encode
from the original webm.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz
@brandomr

Copy link
Copy Markdown
Contributor Author

Pushed a red-team pass (11b7c52). The interesting outcome: the credentials section in v1 was wrong about the mechanism.

I had blamed shell environment variables for API keys surviving isolation. Chasing it properly turned up three separate paths, each now verified against the code and one reproduced live:

  1. .env discovery walks up from the package's own location. locate_envfile() uses find_dotenv(usecwd=False), which searches upward from lib/config.py itself. Reproduced: calling locate_envfile() from a venv three directories deep resolved to a repo-root .env that neither cwd nor $HOME pointed anywhere near. LOAD_DOTENV = false disables it.
  2. Provider classes fall back to env vars (OPENROUTER_API_KEY etc.).
  3. BeakerKernelManager sets the kernel's HOME and cwd to the agent user's passwd-database home, discarding the server's environment. So wrapping the server process isolates nothing that matters; the model client runs in the kernel.

Together these explain why a "first run with no key" is nearly impossible to fake on a developer machine, which is worth having written down.

Also corrected from v1: the cp -R recipe nested ui/ui on a second run; the two skill search roots usually coincide (kernel cwd is set to the home dir); WEIGHT has no tie-break, so strictly-lowest is the requirement. New: a version-skew note for downstream context authors (the first positional arg of SkillIntegrationProvider means display_name on 2.0.9 and id here, with no error either way), the REST endpoints for inspecting a live session, and stable Playwright selectors.

Still zero em dashes.

Context setup runs before PythonSubkernel.setup(), whose init code ends
with 'del importlib, os, site, sys'. Names a context setup procedure
imports at top level are therefore gone before the first agent cell,
and the failure surfaces later as a NameError inside helper functions.
Found the hard way while building a context whose helper printed to
sys.stderr.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant