Skip to content

Commit 155259e

Browse files
authored
Add triggered-by attribution to bot-created GitHub artifacts (#23)
Thread the Slack user's name through the agent call chain so the system prompt can instruct the agent to include "Requested by {name} via Slack" in issues and other GitHub artifacts it creates.
1 parent c71b217 commit 155259e

File tree

6 files changed

+26
-5
lines changed

6 files changed

+26
-5
lines changed

prompts/system.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ You read Slack thread conversations and respond to whatever is being asked. You
2626

2727
Your response will be posted back to the Slack thread — keep it concise and well-formatted for Slack.
2828

29+
## Attribution
30+
31+
When the prompt includes a "Triggered by" line, include attribution in any GitHub artifact you create
32+
(issues, comments, etc.). Add "Requested by {name} via Slack" at the bottom of the body.
33+
2934
## Slack formatting (mrkdwn)
3035

3136
Slack does NOT use standard Markdown. Use Slack's mrkdwn syntax:

skills/create-issue/SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ gh issue create --repo {repo} --title "..." --body "..." --label "bug,Android,cl
4646
- Don't include every message — synthesize the key points
4747
- Include relevant code snippets or error messages from the thread
4848
- If participants disagreed, note the different perspectives
49+
- Include "Requested by {name} via Slack" as the last line of the issue body, using the name from the "Triggered by" metadata. Omit if no "Triggered by" is present.
4950
- Always output the created issue URL as the last line, prefixed with `ISSUE_URL:`

src/agent.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface AgentConfig {
3232
export interface RunOptions {
3333
threadContent: string;
3434
dryRun?: boolean;
35+
triggeredBy?: string;
3536
events?: EventEmitter;
3637
}
3738

@@ -123,7 +124,7 @@ export async function runAgent(options: RunOptions): Promise<RunResult> {
123124
throw new Error("Agent not initialized — call initAgent() first");
124125
}
125126

126-
const { threadContent, dryRun, events } = options;
127+
const { threadContent, dryRun, triggeredBy, events } = options;
127128
const sessionManager = SessionManager.inMemory();
128129

129130
const systemPrompt = readFileSync(
@@ -160,7 +161,7 @@ export async function runAgent(options: RunOptions): Promise<RunResult> {
160161
});
161162

162163
try {
163-
const prompt = buildPrompt(threadContent, dryRun);
164+
const prompt = buildPrompt(threadContent, dryRun, triggeredBy);
164165

165166
if (events) {
166167
subscribeToTextDeltas(session, events);

src/prompt.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
export function buildPrompt(threadContent: string, dryRun?: boolean): string {
1+
export function buildPrompt(threadContent: string, dryRun?: boolean, triggeredBy?: string): string {
22
const dryRunNotice = dryRun
33
? "IMPORTANT: Do not execute any commands. Just describe what you would do.\n\n"
44
: "";
55

6-
return `${dryRunNotice}## Slack Thread\n\n<slack-thread>\n${threadContent}\n</slack-thread>`;
6+
const attribution = triggeredBy
7+
? `Triggered by: ${triggeredBy}\n\n`
8+
: "";
9+
10+
return `${dryRunNotice}${attribution}## Slack Thread\n\n<slack-thread>\n${threadContent}\n</slack-thread>`;
711
}

src/slack.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export async function startSlackBot(config: Config): Promise<void> {
3636
await react("rl-bonk-doge");
3737

3838
const threadContent = await fetchThread(client, event.channel, threadTs);
39-
const { text: response, cost, tokens } = await runAgent({ threadContent });
39+
const { text: response, cost, tokens } = await runAgent({ threadContent, triggeredBy: userName });
4040
await syncAuth();
4141

4242
await unreact("rl-bonk-doge");

test/prompt.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,14 @@ describe("buildPrompt", () => {
2828
const result = buildPrompt(content);
2929
assert.ok(result.includes(content));
3030
});
31+
32+
it("includes triggeredBy when provided", () => {
33+
const result = buildPrompt("hello", false, "Alice");
34+
assert.ok(result.includes("Triggered by: Alice"));
35+
});
36+
37+
it("omits triggeredBy when not provided", () => {
38+
const result = buildPrompt("hello");
39+
assert.ok(!result.includes("Triggered by:"));
40+
});
3141
});

0 commit comments

Comments
 (0)