Skip to content

{{taskBody}} is not expanded in the prompts per the docs #257

@aappddeevv

Description

@aappddeevv

This issue was authored by an agent:

The website docs advertise three template variables for prompts — {{ticket}}, {{taskTitle}}, {{taskBody}} — but only {{ticket}} is actually wired up. {{taskTitle}} and
{{taskBody}} pass through verbatim into the agent prompt, which is almost certainly not what users expect.

What the docs say

website/docs/workspaces-plugin.md (lines 462-464):

- `{{ticket}}`: Replaced with task ID (if ticketMode is "required" or "optional")
- `{{taskTitle}}`: Replaced with task title from TD
- `{{taskBody}}`: Replaced with task description from TD

And again on line 645:

Link tasks to workspaces for context—agents can see task descriptions via {{taskBody}}

What actually happens

internal/plugins/workspace/template.go only matches {{ticket}} / {{ticket || 'fallback'}}:

var ticketPattern = regexp.MustCompile(`\{\{ticket(?:\s*\|\|\s*'([^']*)')?\}\}`)

func ExpandPromptTemplate(body, taskID string) string {
    return ticketPattern.ReplaceAllStringFunc(body, ...)
}

There are no references to taskTitle or taskBody as template names anywhere in the Go code (verified via git grep). Anything other than {{ticket}} falls through unchanged.

Repro

  1. Create/edit a prompt in ~/.config/sidecar/config.json:
    {
      "name": "Repro",
      "ticketMode": "optional",
      "body": "Work on {{ticket}}.\n\nTitle: {{taskTitle}}\nBody:\n{{taskBody}}"
    }
  2. Create a workspace, link a task with title + description, pick this prompt, choose any agent (e.g. claude or copilot).
  3. Inspect the launcher script the agent is actually invoked with — e.g. by tailing ~/.local/state/sidecar/<project>/<worktree>/start.sh while it exists, or by adding a
    slog.Debug in writeAgentLauncher and running with --debug.

You'll see {{ticket}} substituted and {{taskTitle}} / {{taskBody}} left as literal {{taskTitle}} / {{taskBody}} strings in the prompt fed to the agent.

Why it matters

When no prompt template is selected, sidecar already does the right-ish thing: getTaskContext (internal/plugins/workspace/agent.go:776) shells out to td show --json and embeds
Task: <title>\n\n<description> for the agent. So the data is available — it just isn't exposed to prompt authors via {{taskTitle}} / {{taskBody}} even though the docs promise
it.

This means anyone writing a prompt template who follows the docs ends up shipping the literal strings {{taskTitle}} and {{taskBody}} to their agent, which is confusing both for
the user (silent failure) and the agent (random Mustache-looking tokens in the prompt).

Possible fixes (one of)

  1. Implement what's documented. Extend ExpandPromptTemplate to take a small struct ({ TaskID, Title, Body string }), match {{taskTitle}} and {{taskBody}} (with || 'fallback' parity), and thread title/body in from buildAgentCommand — they're already on Worktree (TaskTitle) or fetchable via getTaskContext. Probably the better option
    since {{taskBody}} is genuinely useful.
  2. Fix the docs. Strip {{taskTitle}} and {{taskBody}} from website/docs/workspaces-plugin.md (lines 462-464 and the mention on line 645). Cheap, but loses functionality
    the docs imply.

Happy to PR option 1 if there's appetite for it.

Refs

  • internal/plugins/workspace/template.go — current single-variable expander
  • internal/plugins/workspace/agent.go:550-552 — where ExpandPromptTemplate is invoked
  • internal/plugins/workspace/agent.go:776 (getTaskContext) — existing path that already pulls title+body
  • website/docs/workspaces-plugin.md:462-464, 645 — the over-promise
  • .claude/skills/create-prompt/SKILL.md — accurate, only documents {{ticket}}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions