chore: added RedTeamExperiment round-trips - #263
Conversation
|
Assessment: Comment (approve-leaning) Solid, well-scoped addition of Review Categories
Nice work — the docstrings and inline rationale (esp. around the |
3f4edc2 to
ad18b3d
Compare
ad18b3d to
e919a10
Compare
|
Assessment: Approve Re-reviewed after the latest push — all four threads from the previous round are addressed in code, not just marked resolved. Verified locally: 18 tests pass, ruff clean. Verification of resolved threads
Clean execution on the follow-up — thanks for the thorough turnaround. |
The Model ABC contract is `get_config()`; `.config` is a BedrockModel implementation detail. Providers that store config elsewhere would have silently dropped the model id on round-trip. Switch to the documented accessor with the same dict guard. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Assessment: Approve Re-reviewed after commit |
Resolve crescendo conflict: keep the lifecycle refactor (fresh judge/refusal-judge built per call via make_judge factory, attacker per run_attack, no cached agents, reset() not overridden) AND adopt upstream strands-agents#263's serialization (CrescendoStrategy.to_dict reading the static config _max_turns/_max_backtracks/ _success_threshold/_model + _serialize_model). Drop upstream's old cached _attacker_agent (superseded by our _build_attacker). base.py auto-merged: our reset() stateless-hook docstring + upstream's to_dict/from_dict coexist. Brings in strands-agents#251 (multi-agent session), strands-agents#263 (RedTeamExperiment round-trips), strands-agents#264 (docs). Full redteam suite 262 passed; round-trip serialization tests green against the stateless strategy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: added RedTeamExperiment round-trips * fix(redteam): use Model.get_config() in _serialize_model The Model ABC contract is `get_config()`; `.config` is a BedrockModel implementation detail. Providers that store config elsewhere would have silently dropped the model id on round-trip. Switch to the documented accessor with the same dict guard. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Description
RedTeamExperimentnow round-trips throughto_file/from_file(andto_dict/from_dict).Currently Live targets (agent) are not JSON-serializable, so we'll need load-then-plug-in:
What's persisted: cases (validated as
RedTeamCaseso the typedconfigsurvives reload), evaluators, attack strategies, and the experiment-levelmodelid. What's deliberately omitted: the liveagent(Agent/MultiAgentBase/TargetSession) and per-run state (_run_meta).Changes
AttackStrategy.to_dict/from_dict(base): emitsstrategy_type+label;from_dictresolves against a built-in registry (CrescendoStrategy,PromptStrategy) plus acustom_strategies=[...]escape hatch.CrescendoStrategy.to_dict: persistsmax_turns,max_backtracks,success_threshold, andmodel(when set, as a string id).PromptStrategy.to_dict: persistsstrategy_name,system_prompt_template,max_turns.RedTeamExperiment:agentproperty + setter (andattack_strategiesread-only view).to_dictoverride addsattack_strategiesandmodel; never persistsagent.from_dict/from_fileoverrides acceptcustom_evaluatorsandcustom_strategies, auto-registerAttackSuccessEvaluator, and validate cases asRedTeamCase._serialize_modelhelper instrategies/base.py: coercesModel | str | Noneto a JSON-safe id; preservesNone(so a strategy's "defer to experiment-level model" semantic survives a round-trip).Why setter, not constructor injection at load time
A loaded experiment is a complete config object containing case set, evaluators, strategies, model, and is valid even without an agent. Only
_default_taskreads the agent, so deferring attachment until just beforerun_evaluationsmirrors howcasesandevaluatorsare already exposed as settable properties on the baseExperiment. Callingrun_evaluations()with no agent and no explicittask=still raises the existing message.Related Issues
Type of Change
New feature
Testing
5 new tests in
tests/strands_evals/experimental/redteam/test_experiment.py:test_agent_setter_round_trip— setter accepts a target after construction.test_to_dict_persists_strategies_and_model— exact serialized shape; verifiesagentis omitted.test_from_dict_round_trip_runs_after_setting_agent— full file round-trip, raise-without-agent, then run after attaching.test_from_dict_accepts_custom_strategies— custom strategy subclass round-trips via the registry hook.test_from_dict_unknown_strategy_raises— clear error when a custom subclass isn't registered.I ran
hatch run prepare(mypy + ruff clean; full redteam suite, 121 tests, passes).Checklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.