Skip to main content
An AI agent can read a netlist, but a netlist alone doesn’t tell it what the box is for or what each wire means. Knowing uart1 is a UART is not the same as knowing it’s the DUT’s debug CLI. DUT context is the narrative you author once so agents reason about your bench at the level of systems, not loose wires. DUT context lives in /etc/lager/bench.json and is surfaced to agents through the MCP resources lager://dut/overview.md and lager://dut/context, and the discover_dut() and cite_schematic() tools.

The two things to author

1. Per-net purpose

Each net carries a single-sentence purpose plus optional notes. Set them in the Net Manager TUI:
lager nets tui --box my-box
Select a net, open its details, and fill in:
  • Purpose“DUT debug CLI over UART; primary command/response channel.”
  • Notes (optional) — gotchas, jumper positions, scope probe points.
  • Tags (optional) — short keywords the planning tools match on, e.g. flash, boot-critical.
purpose and notes are prose for the agent to read; tags are keywords the planning tools score against (a tag matching a test goal is the strongest relevance signal). You can also set these without the TUI:
lager nets describe uart1 \
  --purpose "DUT debug CLI over UART" \
  --notes "PA9/PA10; 115200 8N1" \
  --tag cli --tag boot-critical \
  --box my-box

2. DUT-wide context

The DUT context describes the board as a whole: its purpose, MCU, key peripherals, subsystems, and references to documents. Author it with the lager box dut command group.
# View current context
lager box dut show --box my-box

# Edit the whole DUT block in $EDITOR
lager box dut edit --box my-box
A fully authored DUT context looks like this in bench.json:
{
  "dut_context": {
    "name": "main",
    "purpose": "Power-regression rig for FeatureA boards",
    "mcu": "STM32H7",
    "key_peripherals": ["QSPI flash", "PMIC"],
    "summary": "STM32H7-based DUT used to validate the power tree under fault injection.",
    "schematic_refs": [
      {"title": "Main schematic", "kind": "schematic", "repo_path": "docs/sch.pdf"}
    ],
    "datasheet_refs": [
      {"title": "STM32H7 RM", "kind": "datasheet", "url": "https://...", "pages": "150-200"}
    ],
    "subsystems": [
      {
        "name": "Flash subsystem",
        "summary": "QSPI flash",
        "nets": ["flash_cs", "flash_clk"],
        "doc_refs": [
          {"title": "Flash sheet", "kind": "schematic", "repo_path": "docs/sch.pdf", "pages": "3"}
        ]
      },
      {"name": "Power tree", "summary": "PMIC + LDOs", "nets": ["psu1"]}
    ]
  }
}
Subsystems group related nets (Power tree, Flash subsystem, Debug, …) so the agent reasons about functional blocks. The agent can ask for one net and learn which subsystem it belongs to and which schematic sheet covers it.

Attaching schematics and datasheets

The Lager Box is not a document store. It records pointers to your documents; the agent fetches and analyses them with its own (vision-capable) tools. This keeps the box lean and lets the agent use the best tool for reading a PDF or board image. Attach a pointer without hand-editing JSON:
lager box dut add-doc --kind schematic \
  --title "Main board" --repo-path docs/sch.pdf --pages 3-5 --box my-box

lager box dut add-doc --kind datasheet \
  --title "STM32H7 reference manual" --url "https://..." --pages 150-200 --box my-box
A document reference (DocRef) has:
FieldMeaning
titleHuman label.
kindschematic, layout, datasheet, firmware, manual, errata, or other.
urlExternal URL (any URL the agent can fetch).
repo_pathPath relative to your test project (synced to the box on lager python).
pagesOptional page/sheet hint, e.g. "3-5" or "POWER sheet".
notesOptional free-form note.
You must supply at least one of --url or --repo-path.

URL vs. repo-path: which to use

SituationRecommendedWhy
Automated / CI / headless agent--repo-pathThe file is synced with your project; no network, no auth, fully deterministic.
Publicly fetchable doc--urlAny agent with a web-fetch tool can pull it.
Private doc (Google Doc, Confluence, SSO)--repo-path or a Drive connectorThe box never authenticates; a login-walled URL returns an auth page, not content.
For Google Docs, prefer an export URL over the editor URL — the /edit URL returns the JS app, not the content:
https://docs.google.com/document/d/<DOC_ID>/export?format=pdf
Either share it “anyone with the link,” give your agent a Google Drive connector/MCP server that holds the credentials, or export it into your repo and use --repo-path.

How the agent uses it

Once authored, the context drives the whole agent loop:
  1. The agent reads lager://dut/overview.md and learns: “power-regression rig, STM32H7, flash + power-tree subsystems, schematic at docs/sch.pdf.”
  2. plan_firmware_test("flash driver", "exercise QSPI") returns a plan already scoped to the flash subsystem, with a pointer to schematic page 3.
  3. cite_schematic("flash_cs") returns just the refs for that net:
    {
      "net": "flash_cs",
      "net_purpose": "SPI flash chip-select",
      "subsystem": "Flash subsystem",
      "subsystem_doc_refs": [
        {"title": "Flash sheet", "repo_path": "docs/sch.pdf", "pages": "3"}
      ]
    }
    
    The agent opens docs/sch.pdf at page 3 with its own file tools — no scanning the whole PDF.

Applying changes

The MCP server watches /etc/lager/bench.json, /etc/lager/saved_nets.json, and /etc/lager/box_id and auto-reloads when any of them changes on disk. So after lager box dut edit, lager box dut add-doc, or lager nets describe, agents see the new context on their next discover_dut(), discover_bench(), or lager://dut/overview.md request — no manual step required. If you want to force a reload immediately (e.g. to confirm a change took), a connected agent can still call the box_manage tool with action="reload", or you can restart the box service.