Draft: feat: Add agent cli with calibration example
Add yade-agent: a command-line client for controlling live simulations
Summary
This MR adds yade-agent, a structured command-line client for launching a Yade simulation, driving it while it runs, and reading results back — one subcommand at a time. It's designed to be easy for a script or an AI agent to operate, and is the structured counterpart of the existing telnet "Python prompt": instead of a raw REPL it speaks newline-delimited JSON to an in-process control server over a per-user Unix-domain socket.
It complements the recently documented MCP bridge: the MCP bridge targets MCP-native agents, while yade-agent serves shell-driven agents and plain scripting, with no extra runtime dependencies.
What's included
| Component | File |
|---|---|
| In-process JSON control server | py/agentserver.py |
| CLI client | core/main/yade-agent.in |
| Build/install wiring | CMakeLists.txt (configure + install yade${SUFFIX}-agent) |
| CLI reference docs | doc/sphinx/user.rst (new "Command-line agent control" subsection) |
| Worked example page | doc/sphinx/AgentCalibration.rst (+ toctree entries) |
| Example script & figure | doc/sphinx/agent-calibration/triax_server.py, doc/sphinx/fig/agent-calibration-convergence.png |
How it works
yade-agent start SCRIPT --name Xlaunches a detached, headless Yade process that runs the script and then serves a control socket, so the process stays alive without a TTY.- Subcommands
list / status / run / pause / exec / plot / save / stop / logsaddress a session by id, name, or@last, and accept--json. - The control server (
yade.agentserver) runs in a background thread and executes against the running script's namespace, soO,O.bodies, and script-defined variables are all live. Commands are lock-serialized; the sim loop runs in its own C++ thread viaO.run(..., wait=False). - Security: the socket lives under
$XDG_RUNTIME_DIR/yade-agent(or~/.yade-agent) with0700/0600perms — access is restricted to the local user by the filesystem; nothing is exposed over the network.
Packaging
No manifest changes are needed: the Debian .install files already grab all of usr/bin and usr/lib, so the new executable and agentserver.py (auto-installed by the py/*.py glob) ship automatically. After merge, apt install yade / yadedaily will include yade-agent / yadedaily-agent alongside yade-batch.
Documentation & example
AgentCalibration.rst is a full worked example: an LLM driving yade-agent to calibrate FrictMat micro-parameters (young, comFricDegree) to a target macroscopic triaxial response (E = 5 MPa, strength = 100 kPa). It exploits session persistence — the specimen is compacted once (O.saveTmp) and each trial restores it (O.loadTmp) and re-shears, never re-compacting — and includes a copy-pasteable prompt so users can reproduce it with their own agent. The example converged in 4 trials.
Testing
- Exercised the full lifecycle (
start / status / run / exec / plot / stop, session cleanup, valid-JSON output) against a packaged Yade 2022.01a (aptbuild), running the client as a plainpython3script that auto-detects theyadeexecutable. - Ran the calibration example end-to-end, including the persistent compact-once/shear-many workflow and the combined convergence plot.
Note: I have not yet done a from-source
make installto exercise the CMake install rules, nor a Sphinx docs build — so a CI build is worth confirming, in particular that the:yref:targets inAgentCalibration.rst(Omega.saveTmp/loadTmp,PWaveTimeStep,CohFrictMat) resolve. Happy to soften any that warn.
Known limitations / possible follow-ups
stopis asynchronous (the process exits shortly after replying), so a same-namestartcan race a not-yet-dead session. Workaround today is unique names /@last; astop --waitor start-side wait would be cleaner.- Each session still also starts the legacy
yade.remotetelnet(9000)/xmlrpc(21000) servers — harmless but redundant; a--no-remoteflag could suppress them. - No man page yet (
debian/rulesgenerates them foryade/yade-batch); can be added.