feat(simulator): structured_output for ActorSimulator#207
feat(simulator): structured_output for ActorSimulator#207poshinchen wants to merge 6 commits intostrands-agents:mainfrom
Conversation
4eff519 to
2967b7e
Compare
|
I want to pitch a slightly different shape for this feature. The issue is that Instead, if we wrote.... ....then this would have the following behavior.
This collapses the two methods into one because passing a Pydantic class is already an unambiguous request for structured output. There's nothing additional for a flag to disambiguate. A caller who doesn't want the new behavior doesn't pass the kwarg, and everything works as it does today. A caller who does want it passes the kwarg once at construction and uses So concretely, this would mean
|
|
|
||
|
|
||
| def test_init_with_input_type_narrows_message_schema(sample_actor_profile): | ||
| """With input_type, act_structured() hands a ActorStructuredResponse subclass whose message is typed.""" |
There was a problem hiding this comment.
Nit: "an ActorStructuredResponse"
Allow users to set the structured output model once at construction time instead of passing it on every act() call. The init-level model is used as the default for act() and can still be overridden per-call. Validates at init time: must subclass ActorOutputBase and have a 'message' field. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ff3461a to
4cdd3bd
Compare
4cdd3bd to
da32699
Compare
da32699 to
8ab3f20
Compare
Simplifies the fallback chain in act() — no need for a triple-or since the instance attribute always holds a valid model. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8ab3f20 to
dce76a4
Compare
Summary
Adds structured stop-signalling and custom output schema support to
ActorSimulator, replacing the<stop/>text sentinel with a properstop: boolfield on the structured response.Breaking Changes
ActorResponse.messagechanged fromstr(required) tostr | None(optional, defaultNone)ActorResponse.stop == Trueinstead of parsing<stop/>from message textActorResponsefields added:stop: boolandstop_reason: str | NoneKey Changes
__init__accepts keyword-onlystructured_output_model: type[BaseModel] | None, validated at construction and used as the default for allact()callsact()accepts per-callstructured_output_modeloverride; any PydanticBaseModelwithmessageandstopfields.stop_reason:"goal_completed"or"max_turns"system_prompt_templatedefaults toDEFAULT_USER_SIMULATOR_PROMPT_TEMPLATEand supports pre-rendered strings (no{actor_profile}placeholder required)stop=true" instead of "generate<stop/>"What Changed
types/simulation/actor.pyActorResponse.message:str→str | None = NoneActorResponsegainsstop: bool = Falseandstop_reason: str | None = Noneactor_simulator.pystructured_output_modelkwarg on__init__, validated via_validate_output_model()(checksmessageandstopfields exist)act()resolution order: per-call → init-level →ActorResponsestopfrom structured output, setsstop_reason, enforcesmax_turnshas_next()simplified toreturn not self.stop_last_messagetracking and<stop/>sentinel parsingprompt_templates/actor_system_prompt.pystop=truein your structured response" replaces "generate<stop/>"Usage
Default usage (no custom model):
Testing
25 unit tests covering init-level and per-call
structured_output_model, field validation (messageandstoprequired),stop_reasonvalues, custom model stop management, template selection, and default promptstop=trueinstruction.Type of Change
Breaking change + new feature
Checklist
hatch run prepareBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.