agentic-hil
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| AGENTIC_HIL_CONFIG | No | Absolute path to the authoritative configuration file. Normally discovered automatically from the platform config directory; this override is only needed when an operator-controlled absolute-path override is required. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| debugger_infoA | Check the debugger backend is installed: runs only --version, at most 10 s; contacts no probe or board. Replaces openocd. Returns backend, executable, version, config_status. Next: debugger_probes_list (probe ids), probe_target (board). Failures: debugger_not_found (missing), timeout; not_supported unless exactly one debugger is configured; permission_denied without allow_probe (config version 1). |
| debugger_probes_listA | List the probe ids of the in-circuit debuggers or programmers on this host; connects to no board. Replaces st-info. Returns probes, each with a probe_id to set as the debugger entry's probe_id. pyOCD and STM32CubeProgrammer ask their CLI; OpenOCD reads the USB serial inventory, complete false (adapters it cannot read there: not_supported). Failure: probe_discovery_failed. |
| probe_targetA | Connect the in-circuit debugger or programmer to the board and confirm it answers (target_detected true), with no reset and no flash; reset_target resets. Replaces openocd. Refused with resource_busy while a debug session is open. Failures: adapter_not_found (no probe), target_not_detected (board silent), debugger_not_found (backend missing), timeout (one command over debugger.timeout_s). |
| artifact_uploadA | Store a firmware image in artifacts.upload_directory and return its artifact_id for flash_firmware or debug_start_session; no board needed. Give image_path, or filename with data_base64, else invalid_argument. Needs allow_upload, else permission_denied. The id is the sha256 of the bytes plus the lowercased extension: same bytes and extension, same id. Unsafe destination: unsafe_configured_path. |
| flash_firmwareA | Write firmware to the board via the in-circuit debugger or programmer, not st-flash; every call writes it again. Needs allow_flash, else permission_denied. resource_busy: debug_stop_session first; device_busy: held elsewhere. The debugger entry's timeout_s (seconds, 60 unless set) caps each debugger command, else timeout. No bench_run_start needed; capture with reset_after_flash adds boot output. |
| reset_targetA | Reset the board through the in-circuit debugger or programmer: the firmware restarts, flash is kept. Replaces st-util. Needs allow_reset (else permission_denied). Refused with resource_busy while a debug session is open: debug_stop_session first. To check the board without a reset use probe_target. Failures: reset_failed (reset not confirmed), timeout (one command over debugger.timeout_s). |
| debug_start_sessionA | Opens a GDB session on an ELF for debug_continue and debug_halt. OpenOCD backend only; others answer not_supported. Needs GDB (debug.gdb_executable or PATH), the debugger entry's scripts and allow_raw_debugger_commands off. Returns the core halted: session (status, stop_reason), log_path. A second start: session_already_active. debug_get_session_status inspects it; debug_stop_session ends it. |
| debug_stop_sessionA | Ends the debug_start_session session; debug_halt keeps it open. Confirms the core halted, disables resume on detach, ends GDB and the debug server, drops breakpoints, frees flash_firmware and reset_target. OpenOCD backend only; others answer not_supported. Success: safe_state_confirmed true. No session: ok, active false. Unproven: ok false, cleanup_required, hardware_state unknown, quarantined. |
| debug_get_session_statusA | Reports if the debug_start_session session is open and its status: halted, running, error or cleanup_required. Records new stops, but never halts or resumes the core; debug_halt halts, debug_get_stop_reason reads the last stop. Abnormal stop: ok true, target_ok false, target_error_type. No session: ok, active false, status stopped. OpenOCD only, exactly one debugger configured; else not_supported. |
| debug_set_breakpointA | Adds a breakpoint in the debug_start_session session (else session_not_active) without resuming the core. Each call adds one and returns its breakpoint id; debug_list_breakpoints lists them. A location without a grant answers permission_denied. An unconfirmed insert answers cleanup_required; call debug_clear_breakpoints. OpenOCD only, exactly one debugger configured; else not_supported. |
| debug_list_breakpointsA | Lists the breakpoints debug_set_breakpoint added in the debug_start_session session, from the session's own record without asking GDB: breakpoints (id, backend_id, location). Never halts or resumes the core. No session: ok, active false, breakpoints empty. debug_clear_breakpoints removes them and checks GDB. OpenOCD only, exactly one debugger configured; else not_supported. |
| debug_clear_breakpointsA | Removes every breakpoint GDB holds in the debug_start_session session (else session_not_active), then checks none is left. It neither resumes nor halts the core. It answers cleared (the count) and backend_reconciled true; a second call clears 0. Unconfirmed: ok false, breakpoint_reconciliation_failed; a retry is safe. OpenOCD only, exactly one debugger configured; else not_supported. |
| debug_continueA | Resumes the core in the debug_start_session session until it stops. Needs allow_debug_execution, else permission_denied. Returns stop_reason, stop (frame): breakpoint_hit is ok; unexpected_breakpoint and target_exception are not. An exception or debugger_error stop is not resumed. No session: session_not_active. OpenOCD only, exactly one debugger configured; else not_supported. |
| debug_haltA | Halts the core; the session stays open. It needs debug_start_session (else session_not_active) on OpenOCD with exactly one debugger configured, else not_supported. debug_continue resumes. Returns stop_reason halted or a stopped core's recorded stop. If an acknowledged interrupt's stop times out, ok and halt_confirmed are false, target_state unknown, bench quarantined; a confirmed halt can lift it. |
| debug_get_stop_reasonA | Why the core last stopped: stop_reason (breakpoint_hit, halted, exception), stop (frame). Records a newly arrived stop; never halts or resumes the core. Abnormal stop: ok true, target_ok false, target_error_type. None yet: stop_reason_not_available. Without debug_start_session: session_not_active. Session: debug_get_session_status. OpenOCD only, exactly one debugger configured; else not_supported. |
| debug_symbol_infoA | Find an allowed symbol's hex address, size_bytes and resolved_from in the ELF. Reads no target memory; for bytes use debug_symbol_value, for Intel HEX debug_dump_symbol_ihex. OpenOCD needs debug_start_session (else session_not_active). pyOCD and STM32CubeProgrammer use the ELF this server last flashed via flash_firmware (else symbol_source_not_available; symbol_source_changed if changed since). |
| debug_symbol_valueA | Reads a symbol from target memory, like gdb print. debug_symbol_info gives its address, debug_dump_symbol_ihex a file. Returns hex, plus value_unsigned and value_signed at 1, 2, 4 or 8 bytes. OpenOCD needs debug_start_session (else session_not_active); pyOCD and STM32CubeProgrammer, the ELF flash_firmware last wrote (else symbol_source_not_available). Over max_dump_size_bytes: permission_denied. |
| debug_dump_symbol_ihexA | Read an allowed symbol from target memory and write it as Intel HEX to output_path; returns address, size_bytes and output. Value inline: debug_symbol_value. OpenOCD needs debug_start_session (else session_not_active); pyOCD and STM32CubeProgrammer, the ELF last flashed via flash_firmware (else symbol_source_not_available). Over debug.max_dump_size_bytes: permission_denied. |
| get_last_reportA | Return the newest stored hardware report, pass or fail, under |
| classify_last_errorA | Explain the last hardware failure: error_type names it, likely_causes says what to check, report_path and log_path hold the evidence. Unlike get_last_report, it keeps that failure through later successes. source_tool is the failed tool, or reset_target if a flash's recovery reset failed too. Some refusals, such as allow_flash off, record nothing. Needs no board; no failure yet: report_not_found. |
| com_ports_listA | List |
| com_session_startA | Open the serial port a com_ports entry names and hold it, with its machine-wide lock, until com_session_stop; a reader buffers what the board sends for com_read. DTR and RTS are driven as configured on open, which can reset a board. device_busy, resource_busy or com_port_busy: another server, process or program has the port. permission_denied: neither reading nor writing is allowed. |
| com_session_stopA | Close the com_session_start session on port_id: stop its reader, close the port, release its lock. Unread bytes are dropped; the session log at log_path keeps them. Without a session it returns ok with was_active false. If the reader does not end within max(1 s, timeout_s + 0.5 s) of the close, it returns com_port_close_failed and keeps the session registered; call again to retry. |
| com_writeA | Send bytes over the session com_session_start opened on port_id (else session_not_active); needs the port's allow_write (else permission_denied). At most max_write_bytes encoded bytes, 4096 by default. bytes_written counts the bytes sent; a short write returns serial_write_incomplete. Example: com_session_start port_id "uart0", com_write text "hello\r\n", com_read until "\n", com_session_stop. |
| com_readA | Read what the board sent on a COM port session from com_session_start (else session_not_active), instead of screen, minicom or picocom. With until, one call waits for a pattern instead of polling. Each byte is returned once, as text and hex. If until is not seen in time, the answer is still ok, with until_matched false and the bytes so far. |
| can_buses_listA | List every |
| can_session_startA | Open a session on a configured CAN bus for can_send and can_read, until can_session_stop or server exit. Returns |
| can_session_stopA | Close the can_session_start session on bus_id when done with the bus; its lease is released. Its adapter closes unless other participants share the bus. A declared run still holds the bus. can_send and can_read then answer |
| can_sendA | Send one CAN frame (CAN FD on an |
| can_readA | Read the CAN frames your can_session_start session received into |
| bench_run_startA | Declare a run holding the devices a sequence like flash, reset, read needs until bench_run_stop or server exit, no timeout; without one the board is free between calls. All or nothing: a refused start holds none. Other devices fail |
| bench_run_stopA | End the bench_run_start run and release its devices ( |
| bench_run_statusA | Report whether this server has a run open ( |
| test_reactor_runA | Run a test plan file (agentic-hil://reference/test-plan) on the board. For calls made one by one, use bench_run_start, whose open run refuses this with |
| test_reactor_statusA | Follow a detached test_reactor_run by its handle; for a bench_run_start run, use bench_run_status. |
| test_reactor_stopA | Ask a test plan run to stop by writing a request it reads between steps. It finishes the step it is in (a delay or device wait ends early), closes its devices and writes its report; one still starting ends before any step. Answers at once |
| hardware_recoverA | Clear the standing quarantine that blocks hardware calls. Call it when hardware_lease_status shows incident_stands, rather than deleting state files. It needs allow_recover and touches no hardware. A no-contact reason clears with no argument. Any other reason answers recovery_requires_physical_check: ask the operator, pass their answer verbatim as operator_statement, never invent one. |
| hardware_lease_statusA | Read who holds this bench, from any process ( |
| project_config_createA | Generate this workspace's configuration from attached hardware instead of writing one by hand: every permission true except allow_raw_debugger_commands and allow_mass_erase, which it writes false. Never ask for those two to be turned on. Regenerating is the operator's call, not a way to narrow or re-open. |
| project_config_describeA | List the keys project_config_set may change: writable_keys with current_value and value_schema, locked_keys naming in unlocked_by the permission that opens each. Read it before project_config_set instead of guessing; it needs no permission. writes_blocked_by_open_run is true while this server holds a run or session. Bad YAML answers config_invalid, an unreadable file config_unreadable. |
| project_config_setA | Write values you choose to named keys of the configuration file. Call it after project_config_describe lists the keys, rather than editing the configuration file. Device keys need allow_config_description_write, permission keys allow_config_permissions_write, else permission_denied. Permissions only narrow: closing allow_config_permissions_write freezes them all at once (permissions_frozen). |
| project_config_adopt_hardwareA | Fill the configuration keys that still hold placeholders from the attached probe. Call it once a board is attached, so nobody retypes its serial. It may also rename a COM device to its stable name and correct a stale identity_source. It writes only when apply is true, never flashes or erases. A read that leaves the board state unknown may get it reset into halt by recovery (resource_quarantined). |
| project_config_reload_descriptionA | Re-read target, debuggers, com_ports and can_buses from this workspace's configuration into the running server, never permissions or debug. Call it after project_config_set, project_config_adopt_hardware or a hand edit, rather than a restart. New devices get every permission false; changed grants need a restart (restart_required_for). description_changes lists what moved. |
| server_upgradeA | Upgrade this installation to the newest release with the uv, pipx or pip that installed it. Use it when the operator asks; it takes no arguments and needs allow_upgrade. Each manager run may take 600 s. running_version stays old until this server restarts. On Windows, ask the operator to run agentic-hil upgrade (upgrade_cli_only_on_host). On failure the operator runs any reinstall_command. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| agentic_hil_embedded_workflow | Safe workflow for using Agentic HIL hardware tools from an AI agent. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| debugger-backends | Which of type, executable, probe_id, target_type, interface, interface_cfg, target_cfg, connect_mode and flash_address each of openocd, stlink and pyocd requires, discovers, ignores, or refuses; when probe_id becomes mandatory; when flash_address is needed; which backend can connect under reset; and which of bootstrap discovery's two enumerations answers on a given host, which decides the type and executable a generated entry gets. |
| errors | Every error_type that carries a concrete fix, with its meaning, ordered remediation steps, and the wrong fix to avoid. Identical to the remediation a failing result carries inline. |
| config-schema | The bundled JSON Schema for the authoritative project configuration: every field, type, enum, default, and per-device permission. |
| config-shape | Which sections a configuration has and what each is for, which are required, and a worked Nucleo-F446RE example; then how to change one field-wise over MCP, the two grants that open the description and the permissions halves, which key each grant opens, and what deliberately cannot be done. Value shapes are read from the shipped schema, not restated. |
| lease-lifecycle | Which device a run locks and for how long, what device_busy and undeclared_device mean, why a crashed run needs no recovery; then lease states, the predicate that decides whether to continue, the auto-recovery branch, and the operator recovery path including --confirm-safe-state, --quarantine-id and --accept-config-change. |
| platform-paths | Where the authoritative configuration, state_root and the machine-wide device locks go on Windows and POSIX, which command touches which of them, what is and is not checked about a configured path, and how AGENTIC_HIL_CONFIG plus a chosen state_root bind a project to another location. |
| target-support | Which field names the target per backend, known-good values for the Nucleo-F446RE, how pyOCD target types are provided by CMSIS packs, how to find and install the right one and where installed packs live, and what doctor's target_support statuses mean, including why 'undetermined' is not a failure. |
| test-plan | Where a plan lives (.agentic-hil/testconfig.yaml), how test_config_path and workspace_root resolve it, and which refusal each mistake earns; which format version admits which step; every step with the entry it routes to and its required and optional keys; the comparator families with their rules; and two plans that run. Generated from the shipped plan schema, not restated. |
| test-plan-schema | The bundled JSON Schema every test plan is validated against: every step, key, type, enum, default, and the x-since-version markers the format's version gate reads. |
TDQS
Scored across 44 tools
The set has several superficially similar status/report tools (debug_get_session_status, debug_get_stop_reason, get_last_report, classify_last_error, bench_run_status, test_reactor_status, hardware_lease_status), but descriptions cross-reference each other explicitly and assign distinct purposes, so an agent can tell them apart. The run-vs-run distinction (bench_run_start vs test_reactor_run) is also carefully delineated. Only minor boundary friction remains among the many 'status' tools.
Names are uniformly snake_case with a clear verb_noun pattern and domain prefixes (debug_*, com_*, can_*, bench_run_*, project_config_*). A few names lack a domain prefix (get_last_report, classify_last_error, artifact_upload, server_upgrade) and project_config_reload_description is an awkward phrasing, but overall the convention is predictable.
44 tools is well beyond the 25+ heavy threshold. The domain is genuinely broad (debug, flash, serial, CAN, config, recovery, bench orchestration), but the surface is bloated with many fine-grained session/status/breakpoint tools that could be consolidated. This is a lot of surface for an agent to navigate reliably.
Coverage is remarkably thorough: each subsystem has full lifecycle tools (session start/stop, breakpoint set/list/clear, read/write), plus flash, reset, symbol inspection, bench-run orchestration, config describe/set/adopt/create, error classification, and quarantine recovery. No obvious dead ends for the stated hardware-in-the-loop purpose.