Skip to content

[Feature] Add append_instructions to Signature #9829

Description

@mathurk1

What feature would you like to see?

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.

Usage will look something like:

# Read dynamic instructions from detailed_instruction_file.md
with open("detailed_specific_instruction_file.md", "r") as f:
    detailed_specific_instructions = f.read()
ExtractInformationInformation = ExtractInformation.append_instructions(detailed_specific_instructions)
extractor = dspy.Predict(ExtractInformationInformation)

Would you like to contribute?

  • Yes, I'd like to help implement this.
  • No, I just want to request it.

Additional Context

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.

Activity

  1. MaximeRivest commented on May 26, 2026

    @MaximeRivest
    Collaborator

    I like that suggestion @isaacbmiller, @okhat what do you think?

  2. isaacbmiller commented on May 26, 2026

    @isaacbmiller
    Collaborator

    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 ?

  3. mathurk1 commented on May 27, 2026

    @mathurk1
    ContributorAuthor

    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.

    Please let me know your thoughts, thanks!

  4. MaximeRivest commented on May 27, 2026

    @MaximeRivest
    Collaborator

    maybe it's time to make this a reality.

    class MySignature(dspy.Signature):
        personality = dspy.SystemField("", trainable = True)
        hourly_rate = dspy.SystemField("", trainable = False)

    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?

  5. isaacbmiller commented on May 28, 2026

    @isaacbmiller
    Collaborator

    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

    wdyt @MaximeRivest ?

  6. dhruviervu commented on May 28, 2026

    @dhruviervu

    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.

  7. mathurk1 commented on Jun 1, 2026

    @mathurk1
    ContributorAuthor

    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 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.

    Please let me know your thoughts, thanks!

  8. mathurk1 commented on Jun 10, 2026

    @mathurk1
    ContributorAuthor

    hey @isaacbmiller @MaximeRivest - just checking in - please let me know your thoughts, thanks!

  9. isaacbmiller commented on Jun 10, 2026

    @isaacbmiller
    Collaborator

    Yeah sounds good to me - thanks for your patience!

    Feel free to tag on the PR for a review once its up!

  10. mathurk1 commented on Jun 16, 2026

    @mathurk1
    ContributorAuthor

    hey @isaacbmiller - thanks - I have raised a PR for this: #9846

    Please let me know if any thoughts or concerns.

  11. isaacbmiller commented on Oct 7, 2026

    @isaacbmiller
    Collaborator

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions