Skip to content

Dynamic system prompts for custom agents #3195

Closed

Description

@Flux159

Hi, I am writing a few custom agents using the markdown format as described here: https://opencode.ai/docs/agents#markdown. Currently I'm able to add custom tools via the ~/.opencode/tool folder & then specify them in the markdown frontmatter to customize the tools available for said agent. This works well enough when the system prompt is static & then the agent can use the tools to retrieve additional information, however it doesn't seem to support dynamically generating the system prompt before any tool calls.

What I wanted to do is allow the system prompt for the agent to dynamically add additional information (without having to use tool calls after the first message for this). This doesn't seem to be possible in markdown (or in the agent json format using a prompt with {file://...) since that simply reads the file).

Not sure if this is the correct code path, but I was taking a look at agent.ts and it seems to use system.ts to add environment information dynamically:
https://github.com/sst/opencode/blob/dev/packages/opencode/src/agent/agent.ts
https://github.com/sst/opencode/blob/dev/packages/opencode/src/session/system.ts#L33

I would want to do something similar, but configurable per agent for different use cases. Essentially supporting either json prompt w/ {file://path/to/typescriptpromptorplugin.ts} or somehow being able to also configure prompt via the markdown frontmatter in a similar way (note that I don't have full context of opencode's codebase so this may not be the right approach).

I was also looking at plugins to see if this is possible with plugins, but going from the list of plugin events, I don't believe that this is possible by using the existing plugin events? https://github.com/sst/opencode/blob/dev/packages/sdk/js/src/gen/types.gen.ts#L1175

One other benefit of being able to dynamically create the system prompt is you avoid a number of initial tool calls & requests to an LLM to get dynamic information for your agent to operate. In other words, something like this:

system (w/ tools to get info) -> 
user request -> 
initial tool calls [N] to get dynamic info -> 
start working on user request

Becomes this:

system + dynamic data preloaded (still with tools, but potentially fewer tools since no need for agent to get dynamic info) -> 
user request -> 
start working on user request

I was wondering if there was currently a way to dynamically create the system prompt for an agent or if this was on the roadmap. Alternatively, if someone can give a code pointer to where I could potentially customize the prompt via code (via typescript file checking / loading or some other method), I could see if I can make a PR to get feedback / comments. Thanks!

Activity

  1. rekram1-node commented on Oct 15, 2025

    @rekram1-node
    Collaborator

    @Flux159 do you want it to be hyper dynamic with plugins or would it be good if the agent definitions supported other ways of injecting context, for example with commands we have:

    !echo hello -> becomes -> "echo hello"

    example for commands: https://opencode.ai/docs/commands/#shell-output

    We wanna make this "templating" consistent in other places (also shell output isn't the only thing it handles) and currently this templating is NOT supported for agents

    Would something like that suffice for your use case? Or are you looking for a plugin to edit system prompts given certain events

  2. Flux159 commented on Oct 15, 2025

    @Flux159
    Author

    @rekram1-node - Oh I didn't know about that bash command functionality - I think if that was supported in the agent markdown that would technically allow for any dynamic content w/out needing custom JS? I guess there's no reason I couldn't just do something like:

    This is markdown.
    
    !`node myscript.js`
    
    This is static again.

    I did a (very quick) prototype of allowing custom JS files as system prompts in #3197 which would've just enabled using js or typescript files inside of file:// prompts - similar to how custom tools are defined / exported, but I'm not tied to any specific method.

    Re: Edit system prompts given certain events - I wasn't thinking about this for this issue - I would need to think through what are the right use cases (it would also make it very difficult to debug a single agent session potentially? Like in the middle of a session, the system prompt changes, so any logs that you have would need to indicate that). I don't have any specific uses of this right now, but can add to a discussion here if I think of some later.

  3. rekram1-node commented on Oct 15, 2025

    @rekram1-node
    Collaborator

    I don't have any specific uses of this right now, but can add to a discussion here if I think of some later.

    No need to discuss here I think we have another issue that has that

    Perfect I think making the command syntax more universal is best move here then

  4. taqtiqa-mark commented on Oct 16, 2025

    @taqtiqa-mark
  5. Flux159 commented on Oct 16, 2025

    @Flux159
    Author

    @rekram1-node Put up a new PR that uses templating instead. Works using bun dev for me & seems cleaner since it's consistent with commands.

  6. rekram1-node commented on Oct 16, 2025

    @rekram1-node
    Collaborator

    yo thanks! ill take a look in a bit

  7. taqtiqa-mark commented on Oct 16, 2025

    @taqtiqa-mark

    Note to self... the need for a dedicated SYSTEM.md prompt also applies to subagents. Depending on your set-up perhaps even more so. I such case, extending the layout logic:

    agent/ide.md
    agent/ide-SYSTEM.md
    agent/ide/create-ticket.md
    agent/ide/plan.md
    agent/ide/plan-SYSTEM.md
    
    ...
    

    While this keeps sub-agent SYSTEM.md Prompt content along side their parent agent Prompt and its System Prompt, and renders them easily editable. It does mean the OC parsing logic for sub-agents is no longer a simple file lookup:

    • Now consuming the command file text @ide/plan
    • Needs to resolve to:
      • Submit System message for sub-agent plan session agent/ide/plan-SYSTEM.md
      • Submit User message for sub-agent plan session agent/ide/plan.md

    @Flux159, if you also want to make the Sub-Agent's System Prompt/Message dynamic, you'll need different event hook..... nothing intuitive comes to mind.

  8. FergusFettes commented on Oct 19, 2025

    @FergusFettes

    Would love to see this feature! Being able to dynamically inject context into the system prompt would be super useful for custom agents.

    Just saw the discussion about templating with shell commands (like !command``) - that would be perfect for my use case with headless background agents. Looking forward to this!

    For now I'm working around it by putting dynamic instructions in ~/.config/opencode/AGENTS.md but per-agent dynamic prompts would be much cleaner.

    +1 for this feature!

  9. towry commented on Oct 25, 2025

    @towry

    I like this feature too.

    In claude, it can start with a custom system prompt, so i have a "kiro" workflow that in the system prompt i give the kiro spec doc location and instructions. The best part is after /compact run, this key context will always remain, so the agent will not forget what he is and where the kiro spec doc is.

    But in opencode, currently I achieve this through the --prompt argument, in /compact or auto compact, this context will be lost!

  10. dehidehidehi commented on Nov 18, 2025

    @dehidehidehi

    !echo hello -> becomes -> "echo hello"
    example for commands: https://opencode.ai/docs/commands/#shell-output

    We wanna make this "templating" consistent in other places (also shell output isn't the only thing it handles) and currently this templating is NOT supported for agents

    I use the 'instructions' field in the opencode.json configuration file, as documented here https://opencode.ai/docs/config/#instructions
    For instance :

    {
      "$schema": "https://opencode.ai/config.json",
      "instructions": [
        "~/.config/opencode/context/global/global-context.md",
        "~/.config/opencode/context/global/session-context.md"
      ]
    }

    Global context (exerpt)

    # Current session metadata
    - term.program: 
    !`echo $TERM_PROGRAM`
    - term.colors: 
    !`echo $COLORTERM`
    - term.type: 
    !`echo $TERM`
    - pwd: 
    !`echo $PWD`
    - shell: 
    !`echo $SHELL`
    - xdg.session.type: 
    !`echo $XDG_SESSION_TYPE`

    Yet, despite this being a rule, when I ask an primary agent in opencode what it's current session metadata is, it litterally replies with this (I did not edit the LLM answer):

    Here is the session context I am currently operating with:
    
    - Terminal program: (value from `echo $TERM_PROGRAM`)
    - Terminal colors: (value from `echo $COLORTERM`)
    - Terminal type: (value from `echo $TERM`)
    ...
    

    So far I have not been successful in having shell commands executed as instructions, am I doing something wrong ?

    Thank you,

  11. rekram1-node commented on Nov 18, 2025

    @rekram1-node
    Collaborator

    @dehidehidehi u arent doing anything wrong we will fix this soon, rn the commands only execute for command markdown definitions this is confusing and bad behavior will fix

  12. cinsua commented on Dec 11, 2025

    @cinsua

    I think I accomplished this doing a custom plugin:

    import type { Plugin } from "@opencode-ai/plugin";
    export const ContextInjectionPlugin: Plugin = async ({ client, directory }) => {
      return {
        "chat.message": async (input, output) => {
    
          const userPrompt = output.parts
            .filter((part) => part.type === "text" && !part.synthetic)
            .map((part) => part.text)
            .join("\n");
    
          // You can do something with your userPrompt like RAG or something
          const exampleContextInjected = `Just an example using userPrompt...${userPrompt}`;
    
          // prepare your contextInjection, this will not be shown in TUI
          const contextInjection = `IMPORTANT: Before responding, say the exact textual content of this: ${exampleContextInjected}`;
    
          output.parts.push({
            id: "system-modifier",
            messageID: output.message.id,
            sessionID: input.sessionID,
            type: "text",
            synthetic: true,
            text: contextInjection,
          });
        },
      };
    };
    

    this is not in the docs tho

  13. shanepadgett commented on Jan 2, 2026

    @shanepadgett

    @Flux159 do you want it to be hyper dynamic with plugins or would it be good if the agent definitions supported other ways of injecting context, for example with commands we have:

    !echo hello -> becomes -> "echo hello"

    example for commands: https://opencode.ai/docs/commands/#shell-output

    We wanna make this "templating" consistent in other places (also shell output isn't the only thing it handles) and currently this templating is NOT supported for agents

    Would something like that suffice for your use case? Or are you looking for a plugin to edit system prompts given certain events

    This kind of templating would be great if handled in all markdown files for dynamic purposes. For instance in AGENTS.md if I could run !chezmoi managed -t I could have an agent know that any time it edits any of those files it needs to run commands to keep the dotfiles in sync. I could see uses for !`` output in almost anything we create in markdown format.

  14. einarpersson commented on Jan 10, 2026

    @einarpersson

    would be great to have it universally supported, including SKILL.md files

  15. huankimtran commented on Feb 1, 2026

    @huankimtran

    looking forward to this feature as well team!!

  16. github-actions commented on Apr 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.

  17. einarpersson commented on Apr 3, 2026

    @einarpersson

    If the issue is still relevant please open a new one

    Why open a new one? If it is relevant it is still relevant? Yes this issue is still relevant

  18. adlternative commented on Jun 3, 2026

    @adlternative

    @rekram1-node Has this feature actually started being implemented? It feels like a must-have. If you're busy right now, we can help work on it. :)

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions