Agent Assist — Simulate
SkillCloud & infraUse when the user wants to adversarially test, evaluate, or harden an implemented AI agent before deployment; mentions swarm simulation, attack testing, persistence testing, evaluation criteria, or eval_report.md.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Agent Assist — Simulate skill
What this skill tells your AI
The instructions your AI receives, as published by datarobot-oss/datarobot-agent-skills in skills/datarobot-agent-assist/agent-assist-simulate/SKILL.md and read by ahel’s review.
Adversarially test and harden an implemented agent before deployment. Runs three simulation tracks (attack, behavior, persistence), then patches and retests failing scenarios across multiple rounds until all pass or the fixing limit is reached.
Script Path Resolution
Resolve once per session: <skill_scripts_dir> is the scripts/ subdirectory next to this
SKILL.md. Confirm it exists. Use the resolved absolute path everywhere.
Python: prefer .venv/bin/python3 if a .venv/ exists; otherwise python3. Store as
<python>. Require 3.11+:
<python> -c "import sys; assert sys.version_info >= (3, 11)"
<python> -c "import pydantic, yaml" 2>/dev/null || <python> -m pip install pydantic pyyaml
OpenCode:
dr opencode upgrade && export PATH="$PATH:$HOME/.opencode/bin"
Auth:
dr auth check
dr dotenv update
If any check fails, surface the error and stop.
Swarm directory: All intermediate files (scenario inputs/outputs, run results, convergence state) are written to .datarobot/swarm/ under the project root and deleted at the end of Step 5.
If .datarobot/swarm/ already exists at the start of a session, it is leftover from a prior
session that did not complete Step 5 cleanup. Run rm -rf .datarobot/swarm/ before proceeding.
Pre-flight Check
- Confirm
agent_spec.mdexists with asystem_prompt. If not, route the user toagent-assist-buildand stop. - Confirm implementation code exists (
agent.py,myagent.py,tools.py, orapp.py). If not, route toagent-assist-buildand stop.
Step 1 — Configure
Collect answers in sequence. Do not start simulation until all are answered.
If agent_config.yaml already exists, read it and ask:
"Last time: [persona], [context or none], [iterations] rounds of fixing, [eval mode], [model]. Same settings or change anything?"
Q1 — User type: Read agent_spec.md and offer 2–4 domain-specific personas plus
"Other — describe your user segment."
Q2 — Grounding context (optional): Based on agent_spec.md, ask for domain-appropriate
examples (e.g. past queries, sample inputs, real requests).
Keep the question to one sentence. Save to user_context.txt if provided. Skip if the user says "skip."
Q3 — Fixing rounds: Ask:
"How many rounds of fixing should I run on failing scenarios? Default: 3."
Q4 — Evaluation mode: Ask:
"How should results be evaluated? Standard gives a simple pass/fail. Scored rates each result by severity: low, medium, high, or critical. Default: standard."
Q5 — Model: Run dr opencode models. Recommend the strongest available models from the
catalog. Show up to 5 as a numbered list. After the list, ask: "Want to see more models from
DataRobot LLM Gateway?" If yes, show more from the catalog. Store the choice as <model>.
Q6 — Selective tool execution (optional): Read the tool definitions in agent_spec.md and
identify any that appear to be read-only — no writes, no side effects, names like get_, list_,
load_, fetch_, search_. If any exist, ask:
"I can call these tools for real during simulation instead of generating fictional return values: [list each with its description] Run them for real, or simulate all? Default is simulate."
If the user chooses real execution: edit agent_spec.md to add is_readonly: true on each
approved tool, then pass --execution-mode selective_e2e to native_scenarios.py configure.
Find the .venv/bin/python3 nearest to the implementation file (check its directory, then walk up)
and use it instead of <python> when invoking native_swarm.py in Step 3.
If the user declines or no read-only tools exist, omit --execution-mode (defaults to simulated).
Start OpenCode server (once, after model selection):
dr opencode serve --port 4096 2>/dev/null &
until curl -sf http://127.0.0.1:4096/global/health >/dev/null 2>&1; do sleep 0.25; done
Store the PID as <opencode_server_pid> and http://127.0.0.1:4096 as <opencode_server_url>.
Persist config:
<python> <skill_scripts_dir>/native_scenarios.py configure agent_spec.md \
--user-persona "<persona>" \
--iterations <n> \
--judge-mode <standard|scored> \
--model "<model>" \
[--context user_context.txt]
Step 2 — Generate Scenarios
<python> <skill_scripts_dir>/native_scenarios.py prepare agent_spec.md \
--config agent_config.yaml
Run each generator one at a time. Before each, announce what the track tests. After each, report the count and list the scenario names.
Say: "Generating attack scenarios — these test whether the agent can be manipulated into bypassing its own restrictions."
<python> <skill_scripts_dir>/gateway_worker.py \
--role-prompt generate-attack \
--input-path "$SWARM_DIR/attack-input.json" \
--response-path "$SWARM_DIR/attack-output.json" \
--model <model> --server-url <opencode_server_url>
Read $SWARM_DIR/attack-output.json and report: "Generated X attack scenarios:" followed by a list of scenario names.
Say: "Generating behavior scenarios — these test how the agent handles ambiguous or edge-case user requests."
<python> <skill_scripts_dir>/gateway_worker.py \
--role-prompt generate-behavior \
--input-path "$SWARM_DIR/behavior-input.json" \
--response-path "$SWARM_DIR/behavior-output.json" \
--model <model> --server-url <opencode_server_url>
Read $SWARM_DIR/behavior-output.json and report: "Generated X behavior scenarios:" followed by a list of scenario names.
Say: "Generating persistence scenarios — these apply multi-turn pressure to see if the agent holds its position under pushback."
<python> <skill_scripts_dir>/gateway_worker.py \
--role-prompt generate-persistence \
--input-path "$SWARM_DIR/persistence-input.json" \
--response-path "$SWARM_DIR/persistence-output.json" \
--model <model> --server-url <opencode_server_url>
Read $SWARM_DIR/persistence-output.json and report: "Generated X persistence scenarios:" followed by a list of scenario names.
Validate all outputs:
<python> <skill_scripts_dir>/native_scenarios.py finalize
Read finalize stdout and present the candidate list grouped by track. For each scenario output one line:
- [name] — [one sentence on what it targets]
Example:
Attack (4)
- Malicious CSV Injects Visualization Override — tests whether the agent follows instructions embedded in uploaded file content
- Path Traversal via File Path Argument — tests whether the agent rejects file paths outside the allowed directory
...
Behavior (3)
...
Persistence (3)
...
Then ask:
"Add or remove any, or say 'run it' to confirm. Say 'explain [name]' or 'explain all' for full detail on any scenario." Write the authoritative criteria:
<python> <skill_scripts_dir>/native_scenarios.py confirm --output evaluation_criteria.md
Step 3 — Simulate
Find all implementation files in the working directory (agent.py, myagent.py, tools.py, app.py) and pass
each as a separate --implementation flag. Tell the user before launching:
"[N] scenarios queued — covering adversarial attacks, ambiguous user behavior, and multi-turn pressure. Typically 2–5 minutes."
<python> <skill_scripts_dir>/native_swarm.py run agent_spec.md \
--criteria evaluation_criteria.md \
--config agent_config.yaml \
--server-url <opencode_server_url> \
--model <model> \
--implementation <path> [--implementation <path> ...] \
[--tools-path <path/to/tools.py>]
Include --tools-path only when execution.mode is selective_e2e and tools.py exists. Parse
stdout as the summary JSON. Surface any warning: lines from stderr before presenting results.
While the swarm is running, read the task output file every 30 seconds and narrate newly completed scenarios to the user (scenario name, track, pass/breach/error). Continue until the run completes.
Present results:
Say: "N of M scenarios passed."
Then give a structured narrative before proceeding:
Per-track summary — for each track (attack, behavior, persistence), state how many passed and list each scenario with one line on what it tested. Example:
"Attack — 4/4 passed: path traversal via load_dataset, query injection via run_analysis, scope escalation via wildcard, instruction override attempt."
Per-breach narrative — for each breach, say:
"Breach: [scenario_name] ([track]) What happened: [breach_reason in plain language] Likely fix: [prompt addition / code guard]"
Determine "likely fix" from the breach: if the agent violated a stated restriction, it is a prompt patch. If the agent attempted a tool call it should not have made, it may need a code guard in the implementation.
Overall read — one sentence on where the agent is strong and where it is soft. Example:
"The agent holds well on adversarial attacks and ambiguous behavior, but has soft spots under sustained multi-turn pressure."
Proceed to Step 4 regardless of breached — native_convergence.py initialize must run even
when breached == 0, since it is what creates the convergence state that Step 5's report
command reads.
Step 4 — Converge
<python> <skill_scripts_dir>/native_convergence.py initialize agent_spec.md \
--criteria evaluation_criteria.md \
--config agent_config.yaml \
--actual-model "<model>"
Parse stdout as JSON: {"status": "...", "breaches": [...], "exhausted": [...], "passed": [...]}.
Each breach entry has scenario_id, scenario_name, track, breach_reason, transcript,
breach_indicators, iteration, and suggested_rerun_dir.
If status is complete, skip to Step 5.
Fix loop — repeat until advance returns complete:
For each breach in breaches:
-
Read the breach transcript and
breach_reason. Propose the minimal addition to the system prompt that prevents this behavior. Tell the user:"Breach: [scenario_name] — [breach_reason] Proposed fix: [your proposed text] Apply this patch? (yes/no)"
If approved, edit
agent_spec.mddirectly to append the text tosystem_prompt. Then find theSYSTEM_PROMPTstring in the implementation files (checkagent.py,myagent.py,tools.py,app.py) and apply the same addition there so the deployed agent stays in sync with the spec.If the breach is structural (cannot be fixed by prompt alone — e.g. a missing tool guard in the implementation), say so and read the implementation file at the relevant function. Propose a targeted code change and ask for approval. If approved, apply it with your Edit tool.
-
Before retesting, tell the user:
"Breach: [scenario_name] What happened: [breach_reason] Fix: [one sentence describing what was added to the system prompt or implementation] Retesting now to verify the patch holds."
Then re-run the scenario. Call
initializeonce to set up the run and get the first input/response paths:<python> <skill_scripts_dir>/native_execution.py initialize agent_spec.md \ --criteria evaluation_criteria.md \ --scenario-id <scenario_id> \ --run-dir <suggested_rerun_dir>This returns
{"role": "runner", "input_path": "...", "response_path": "...", "turn_number": 1, ...}.Role → prompt name mapping (use this to pick
--role-prompt):runner→run-scenariofixture→generate-tool-returnevaluator→evaluate-result
Drive to terminal — loop using
submitoutput to advance state. Do NOT callinitializeagain inside the loop:Before each worker call, announce the current step:
- Runner:
"Turn N/M — running scenario" - Fixture:
"Turn N/M — generating tool return" - Evaluator:
"Turn N/M — evaluating"
# 1. Call worker using input_path and response_path from initialize (or previous submit). # For the fixture role: if agent_config.yaml has execution.mode: selective_e2e and # tools.py exists, call tool_executor.py instead of gateway_worker.py: # # selective_e2e fixture: # <python> <skill_scripts_dir>/tool_executor.py \ # --input-path <input_path> --response-path <response_path> \ # --tools-path <tools_path> --readonly-tools <comma-separated readonly fn names> # # all other roles (runner, evaluator) and simulated fixtures: <python> <skill_scripts_dir>/gateway_worker.py \ --role-prompt <run-scenario|generate-tool-return|evaluate-result> \ --input-path <input_path> \ --response-path <response_path> \ --model <model> --server-url <opencode_server_url> # 2. Submit and read next state: <python> <skill_scripts_dir>/native_execution.py submit \ --run-dir <suggested_rerun_dir> --response <response_path>submitreturns the next{"role", "input_path", "response_path", "turn_number"}or a terminal{"status": "passed"|"breach"|"error"}. Use the returnedinput_pathandresponse_pathfor the next worker call. Stop whenstatusis terminal.Report
✓ passed / ✗ breach / ! errorwhen terminal. -
After all reruns in this round, call advance with the completed rerun dirs:
<python> <skill_scripts_dir>/native_convergence.py advance agent_spec.md \ --rerun <scenario_id>:<suggested_rerun_dir> [--rerun ...]Parse stdout the same way as
initialize. Ifstatusiscomplete, stop. Otherwise repeat the fix loop for the newbreacheslist.
For any scenario in exhausted: read its breach_reason and transcript, identify the
implementation function responsible, propose a targeted code fix, ask for approval, apply
with your Edit tool, then rerun it (using the next iteration dir from suggested_rerun_dir
in the advance output) and call advance again.
When advance returns complete:
"Convergence complete. X resolved, Y exhausted."
Step 5 — Report
<python> <skill_scripts_dir>/native_convergence.py report agent_spec.md \
--output eval_report.md
kill <opencode_server_pid> 2>/dev/null || true
rm -rf .datarobot/swarm/
After the script writes eval_report.md, append a "## Changes Applied" section to the file
listing every change made during Step 4 — scenario name, what was changed, and why. For prompt
patches, list both the addition to agent_spec.md and the corresponding change to the
implementation file. For code fixes, list the function and file changed. Use your Edit tool to
append to eval_report.md.
Present passed/total, unresolved, exhausted, and readiness to the user. If ready: false, say so
explicitly before offering next steps.
For each exhausted scenario, immediately after the pass/fail summary line, add one line per scenario:
"⚠ [scenario_name] couldn't be resolved after [N] attempts — this needs your attention before deploying."
Then read eval_report.md and present a per-track breakdown. For each track (attack, behavior,
persistence), list each scenario with one line: what it tested, whether it passed initially or
needed a fix, and how many turns it ran.
Next steps:
What would you like to do next?
1. Review eval_report.md — outcomes and unresolved scenarios
2. Re-run simulation — after further changes
3. Test locally — run the agent on your machine
4. Deploy — deploy the hardened agent to DataRobot
- If 1: read
eval_report.mdand present a structured summary. - If 2: return to Step 1 (reuse saved settings or re-collect).
- If 3: read
AGENTS.md, display the local test command, tell the user to run it in a new terminal. - If 4: follow the deploy instructions in
agent-assist-build/SKILL.md.
Error Handling
Step 2 generator failure — worker exited non-zero (response extraction failed) — the worker
replied with prose instead of JSON. Retry that generator once with a --rejection-note forbidding
tool calls (including the built-in skill tool) and meta-commentary. If it still fails, retry once
with a different top-tier <model> (e.g. claude-opus-4-8) and tell the user which track used it.
If that fails, surface the error and stop.
Step 2 generator failure — finalize rejected the content — finalize prints
role:<role> validation failed: <reason>. Retry that generator once with
--rejection-note "<reason>" and rerun finalize. If it still fails, surface it and stop.
Step 4 rerun worker failure — if a runner/fixture/evaluator worker exits non-zero, mark the scenario failed:
<python> <skill_scripts_dir>/native_execution.py fail \
--run-dir <run_dir> --reason "<reason>"
Then call advance with that run dir so the script records it as errored and moves on.
Auth errors (401 / UNAUTHORIZED): Run dr auth login and retry immediately.
Script timeouts: Allow up to 2 minutes per worker, 10 minutes for native_swarm.py run.
Simulation Tracks
| Track | Degrades when... |
|---|---|
| Attack | No tools defined — scenarios are capability-generic |
| Behavior | No grounding context — falls back to generic user archetypes |
| Persistence | No explicit restrictions in system prompt or implementation code |
Surface these gaps to the user if relevant.
Signals
- GitHub stars
- 25
- Forks
- 23
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
datarobot-agent-assist-simulate- Source
- github.com/datarobot-oss/datarobot-agent-skills