You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature] Add append_instructions to Signature #9829
Currently, Signature provides with_instructions(instructions) which replaces a signature's docstring instructions entirely. AFAIK there's no clean way to add to docstring signature instructions without reading them out manually and reconstructing the signature yourself, which can be brittle IMO.
The proposal is to add another method called append_instructions(instructions) that appends this supplemental instructions to the doc strings rather than replacing it.
I believe it can be useful in scenarios where the signatures are the same, but the instructions can be different. For example, we want to extract information about equipments. The instructions can change depending on the equipment, but the signature + common instructions remain the same.
seems useful, especially for modules that are messing with the underlying signature! However, I don't want to encourage lumping things into instructions that should be an input field.
The instructions can change depending on the equipment, but the signature + common instructions remain the same.
Should be an input field imo
What are the reasons to append to instructions versus pass it as an input field @mathurk1 ?
hey @isaacbmiller from my understanding, input fields end up in the user message as labeled structured content (something like "Your input fields are: 1. my detailed specific instructions (str)"). So if I put task-specific guidance in an input field, the LLM sees it as data to parse rather than direction on how to behave - which isn't quite what I'm going for..
It also feels a bit off from an interface perspective... If I add an input field for specific instructions, every caller will have to pass behavioral config alongside actual input data. Those are two different things and it seems cleaner to keep them separate, IMO
The reason I am proposing append_instructions over an input field is that the signature itself doesn't change - same fields and structure - just the behavioral context/instruction is dynamic. This helps keep the instructions DRY and composable - we can keep common engineer maintained instructions in the docstring/code base and supplement it with business team maintained behavior instructions.
I think @mathurk1 is correct that we both don't want to always have to pass those in AND want a way to put stuff in the system prompt. System prompt, has a special effect on llms behavior.
trainable would add it to the instructions so optimizers can mess with it, false would append it elsewhere in the system prompt so optimizers don't change it.
We need a syntax to pass these values in when the program gets created so we don't passe in at every call and the program signature would not use them.
Yes I was trying to find the thread where we discussed this! #9243 was one recent similar thread
The weirdest part is instantiating here.
Can we do it at signature creation time?
Inherently no, as you are presumably loading this with variables in code. If it was a single small static thing you might just put it in the prompt. Its either too big to put in the prompt or not static.
It could be a signature.with_system_fields(<sys_field>=<value>)
Or I wonder if a module sets it, to keep state out of signatures.
Either you call __call__ with just your Predict.forward(<sys_field>="value") and then it gets remembered? Or it could also be Predict.set_system_field, but I don't want to add new interfaces for this. It should just work
I'd like to take a shot at this. i was thinking to add append_instructions to Signature following the same pattern as with_instructions. Will submit a PR shortly.
As we continue the discussion, wondering if we can go ahead with the append_instructions? This is a natural extension of already existing with_instructions and does not dramatically change any interfaces or implementation paradigms.
In fact with_system_fields feels like a more sophisticated version of with_instructions - structured key-value fields rather than free text. append_instructions sits naturally between the two.
Another concrete use case for the SystemField discussion above came up while reviewing the built-in GEPA InstructionProposer in #10555 (original fork PR: dbreunig#32).
Its constructor currently assembles ProposeInstruction dynamically with conditional signature.prepend calls for reference_skills, additional_instructions, and length_limit, then optionally replaces the signature instructions with with_instructions(base_instructions). These constructor-bound values are supplied again on every proposal alongside the genuinely per-call current_instruction and examples_with_feedback.
This is a useful design case for explicit, structured system-prompt fields: reference material and behavioral guidance should have a declared representation and a clear binding lifecycle, rather than each module building that distinction ad hoc. It also exercises the unresolved ownership question above: where constructor-bound values live without putting mutable instance state on shared signature classes, and which fields optimizers may change.
Please include this proposer as a use case when evaluating the SystemField API. This is a follow-up for that design, not a request to make the proposer PR implement SystemField or a claim that system-message placement alone enforces length constraints.
Activity
MaximeRivest commentedon May 26, 2026
I like that suggestion @isaacbmiller, @okhat what do you think?
isaacbmiller commentedon May 26, 2026
seems useful, especially for modules that are messing with the underlying signature! However, I don't want to encourage lumping things into instructions that should be an input field.
Should be an input field imo
What are the reasons to append to instructions versus pass it as an input field @mathurk1 ?
mathurk1 commentedon May 27, 2026
hey @isaacbmiller from my understanding, input fields end up in the user message as labeled structured content (something like "Your input fields are: 1. my detailed specific instructions (str)"). So if I put task-specific guidance in an input field, the LLM sees it as data to parse rather than direction on how to behave - which isn't quite what I'm going for..
It also feels a bit off from an interface perspective... If I add an input field for specific instructions, every caller will have to pass behavioral config alongside actual input data. Those are two different things and it seems cleaner to keep them separate, IMO
The reason I am proposing
append_instructionsover an input field is that the signature itself doesn't change - same fields and structure - just the behavioral context/instruction is dynamic. This helps keep the instructions DRY and composable - we can keep common engineer maintained instructions in the docstring/code base and supplement it with business team maintained behavior instructions.Please let me know your thoughts, thanks!
MaximeRivest commentedon May 27, 2026
maybe it's time to make this a reality.
We discussed this a while back @okhat and I.
I think @mathurk1 is correct that we both don't want to always have to pass those in AND want a way to put stuff in the system prompt. System prompt, has a special effect on llms behavior.
trainable would add it to the instructions so optimizers can mess with it, false would append it elsewhere in the system prompt so optimizers don't change it.
We need a syntax to pass these values in when the program gets created so we don't passe in at every call and the program signature would not use them.
thoughts?
isaacbmiller commentedon May 28, 2026
Yes I was trying to find the thread where we discussed this! #9243 was one recent similar thread
The weirdest part is instantiating here.
Can we do it at signature creation time?
Inherently no, as you are presumably loading this with variables in code. If it was a single small static thing you might just put it in the prompt. Its either too big to put in the prompt or not static.
It could be a
signature.with_system_fields(<sys_field>=<value>)Or I wonder if a module sets it, to keep state out of signatures.
Either you call
__call__with just yourPredict.forward(<sys_field>="value")and then it gets remembered? Or it could also bePredict.set_system_field, but I don't want to add new interfaces for this. It should just workwdyt @MaximeRivest ?
dhruviervu commentedon May 28, 2026
I'd like to take a shot at this. i was thinking to add append_instructions to Signature following the same pattern as with_instructions. Will submit a PR shortly.
mathurk1 commentedon Jun 1, 2026
hey @isaacbmiller @MaximeRivest - really interesting discussion here!
As we continue the discussion, wondering if we can go ahead with the
append_instructions? This is a natural extension of already existingwith_instructionsand does not dramatically change any interfaces or implementation paradigms.In fact
with_system_fieldsfeels like a more sophisticated version ofwith_instructions- structured key-value fields rather than free text.append_instructionssits naturally between the two.Please let me know your thoughts, thanks!
mathurk1 commentedon Jun 10, 2026
hey @isaacbmiller @MaximeRivest - just checking in - please let me know your thoughts, thanks!
isaacbmiller commentedon Jun 10, 2026
Yeah sounds good to me - thanks for your patience!
Feel free to tag on the PR for a review once its up!
mathurk1 commentedon Jun 16, 2026
hey @isaacbmiller - thanks - I have raised a PR for this: #9846
Please let me know if any thoughts or concerns.
isaacbmiller commentedon Oct 7, 2026
Another concrete use case for the SystemField discussion above came up while reviewing the built-in GEPA InstructionProposer in #10555 (original fork PR: dbreunig#32).
Its constructor currently assembles ProposeInstruction dynamically with conditional signature.prepend calls for reference_skills, additional_instructions, and length_limit, then optionally replaces the signature instructions with with_instructions(base_instructions). These constructor-bound values are supplied again on every proposal alongside the genuinely per-call current_instruction and examples_with_feedback.
This is a useful design case for explicit, structured system-prompt fields: reference material and behavioral guidance should have a declared representation and a clear binding lifecycle, rather than each module building that distinction ad hoc. It also exercises the unresolved ownership question above: where constructor-bound values live without putting mutable instance state on shared signature classes, and which fields optimizers may change.
Please include this proposer as a use case when evaluating the SystemField API. This is a follow-up for that design, not a request to make the proposer PR implement SystemField or a claim that system-message placement alone enforces length constraints.