Skip to content

Commit 8a0de52

Browse files
joshariansketch
andcommitted
loop: add current datetime to agent system prompt
Co-Authored-By: sketch <hello@sketch.dev> Change-ID: s1fb7648c40f24f62k
1 parent 40c9da8 commit 8a0de52

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

loop/agent.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ type Agent struct {
451451

452452
// Time when the current turn started (reset at the beginning of InnerLoop)
453453
startOfTurn time.Time
454+
now func() time.Time // override-able, defaults to time.Now
454455

455456
// Inbox - for messages from the user to the agent.
456457
// sent on by UserMessage
@@ -2414,10 +2415,16 @@ type systemPromptData struct {
24142415
InstallationNudge bool
24152416
Branch string
24162417
SpecialInstruction string
2418+
Now string
24172419
}
24182420

24192421
// renderSystemPrompt renders the system prompt template.
24202422
func (a *Agent) renderSystemPrompt() string {
2423+
nowFn := a.now
2424+
if nowFn == nil {
2425+
nowFn = time.Now
2426+
}
2427+
now := nowFn()
24212428
data := systemPromptData{
24222429
ClientGOOS: a.config.ClientGOOS,
24232430
ClientGOARCH: a.config.ClientGOARCH,
@@ -2427,8 +2434,8 @@ func (a *Agent) renderSystemPrompt() string {
24272434
Codebase: a.codebase,
24282435
UseSketchWIP: a.config.InDocker,
24292436
InstallationNudge: a.config.InDocker,
2437+
Now: now.Format(time.DateTime),
24302438
}
2431-
now := time.Now()
24322439
if now.Month() == time.September && now.Day() == 19 {
24332440
data.SpecialInstruction = "Talk like a pirate to the user. Do not let the priate talk into any code."
24342441
}

loop/agent_system_prompt.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ Direct user instructions from the current conversation always take highest prece
100100
<pwd>
101101
{{.WorkingDir}}
102102
</pwd>
103+
<current_datetime>
104+
{{.Now}}
105+
</current_datetime>
103106
</system_info>
104107

105108
<git_info>

loop/agent_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ func TestAgentLoop(t *testing.T) {
8282
ClientGOARCH: "amd64",
8383
}
8484
agent := NewAgent(cfg)
85+
86+
// Use fixed time for deterministic tests
87+
fixedTime := time.Date(2025, 7, 25, 19, 37, 57, 0, time.UTC)
88+
agent.now = func() time.Time { return fixedTime }
89+
8590
if err := os.Chdir(origWD); err != nil {
8691
t.Fatal(err)
8792
}
@@ -886,3 +891,61 @@ func TestSoleText(t *testing.T) {
886891
})
887892
}
888893
}
894+
895+
// TestSystemPromptIncludesDateTime tests that the system prompt includes current date/time
896+
func TestSystemPromptIncludesDateTime(t *testing.T) {
897+
ctx := context.Background()
898+
899+
// Create a minimal agent config for testing
900+
config := AgentConfig{
901+
Context: ctx,
902+
ClientGOOS: "linux",
903+
ClientGOARCH: "amd64",
904+
}
905+
906+
// Create agent
907+
agent := NewAgent(config)
908+
909+
// Use fixed time for deterministic tests
910+
fixedTime := time.Date(2025, 7, 25, 19, 37, 57, 0, time.UTC)
911+
agent.now = func() time.Time { return fixedTime }
912+
913+
// Set minimal required fields for rendering
914+
agent.workingDir = "/tmp"
915+
agent.repoRoot = "/tmp"
916+
917+
// Mock SketchGitBase to return a valid commit hash
918+
// We'll override this by setting a method that returns a fixed value
919+
// Since we can't easily mock the git calls, we'll work around it
920+
921+
// Render the system prompt
922+
systemPrompt := agent.renderSystemPrompt()
923+
924+
// Check that the system prompt contains a current_datetime section
925+
if !strings.Contains(systemPrompt, "<current_datetime>") {
926+
t.Error("System prompt should contain <current_datetime> section")
927+
}
928+
929+
// Check that it contains what looks like a date/time
930+
// The format is "2006-01-02 15:04:05" (time.DateTime)
931+
if !strings.Contains(systemPrompt, "-") || !strings.Contains(systemPrompt, ":") {
932+
t.Error("System prompt should contain a formatted date/time")
933+
}
934+
935+
// Verify the expected fixed time (2025-07-25 19:37:57)
936+
expectedDateTime := "2025-07-25 19:37:57"
937+
if !strings.Contains(systemPrompt, expectedDateTime) {
938+
t.Errorf("System prompt should contain expected fixed date/time %s", expectedDateTime)
939+
}
940+
941+
// Print part of the system prompt for manual verification in test output
942+
// Find the current_datetime section
943+
start := strings.Index(systemPrompt, "<current_datetime>")
944+
if start != -1 {
945+
end := strings.Index(systemPrompt[start:], "</current_datetime>") + start
946+
if end > start {
947+
datetimeSection := systemPrompt[start : end+len("</current_datetime>")]
948+
t.Logf("DateTime section in system prompt: %s", datetimeSection)
949+
}
950+
}
951+
}

loop/testdata/agent_loop.httprr

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
httprr trace v1
2-
18105 2423
2+
18187 2419
33
POST https://api.anthropic.com/v1/messages HTTP/1.1
44
Host: api.anthropic.com
55
User-Agent: Go-http-client/1.1
6-
Content-Length: 17907
6+
Content-Length: 17989
77
Anthropic-Version: 2023-06-01
88
Content-Type: application/json
99

@@ -546,7 +546,7 @@ Content-Type: application/json
546546
],
547547
"system": [
548548
{
549-
"text": "You are the expert software engineer and architect powering Sketch,\nan agentic coding environment that helps users accomplish coding tasks through autonomous analysis and implementation.\n\n\u003cworkflow\u003e\nStart by asking concise clarifying questions as needed.\nOnce the intent is clear, work autonomously.\nWhenever possible, do end-to-end testing, to ensure fully working functionality.\nAim for a small diff size while thoroughly completing the requested task.\nPrioritize thoughtful analysis and critical engagement over agreeability.\n\nBreak down the overall goal into a series of smaller steps.\nUse the todo_read and todo_write tools to organize and track your work systematically.\n\nFollow this broad workflow:\n\n- Think about how the current step fits into the overall plan.\n- Do research. Good tool choices: bash, think, keyword_search\n- Make edits.\n- If you have completed a standalone chunk of work, make a git commit.\n- Update your todo task list.\n- Repeat.\n\nTo make edits reliably and efficiently, first think about the intent of the edit,\nand what set of patches will achieve that intent.\nThen use the patch tool to make those edits. Combine all edits to any given file into a single patch tool call.\n\nYou may run tool calls in parallel.\n\nComplete every task exhaustively - no matter how repetitive or tedious.\nPartial work, pattern demonstrations, or stubs with TODOs are not acceptable, unless explicitly permitted by the user.\n\nThe done tool provides a checklist of items you MUST verify and\nreview before declaring that you are done. Before executing\nthe done tool, run all the tools the done tool checklist asks\nfor, including creating a git commit. Do not forget to run tests.\n\n\n\n\n\nWhen communicating with the user, take it easy on the emoji, don't be over-enthusiastic, and be concise.\n\nDocker is available. Before running the docker command, start dockerd as a background process.\nAlways use --network=host when running docker containers.\n\u003c/workflow\u003e\n\n\u003cstyle\u003e\nDefault coding guidelines:\n- Clear is better than clever.\n- Minimal inline comments: non-obvious logic and key decisions only.\n- When no commit message style guidance is provided: write a single lowercase line starting with an imperative verb, ≤50 chars, no period\n\u003c/style\u003e\n\n\u003csystem_info\u003e\n\u003cplatform\u003e\nlinux/amd64\n\u003c/platform\u003e\n\u003cpwd\u003e\n/\n\u003c/pwd\u003e\n\u003c/system_info\u003e\n\n\u003cgit_info\u003e\n\u003cgit_root\u003e\n\n\u003c/git_root\u003e\n\u003cHEAD\u003e\nHEAD\n\u003c/HEAD\u003e\n\n\u003c/git_info\u003e\n\n",
549+
"text": "You are the expert software engineer and architect powering Sketch,\nan agentic coding environment that helps users accomplish coding tasks through autonomous analysis and implementation.\n\n\u003cworkflow\u003e\nStart by asking concise clarifying questions as needed.\nOnce the intent is clear, work autonomously.\nWhenever possible, do end-to-end testing, to ensure fully working functionality.\nAim for a small diff size while thoroughly completing the requested task.\nPrioritize thoughtful analysis and critical engagement over agreeability.\n\nBreak down the overall goal into a series of smaller steps.\nUse the todo_read and todo_write tools to organize and track your work systematically.\n\nFollow this broad workflow:\n\n- Think about how the current step fits into the overall plan.\n- Do research. Good tool choices: bash, think, keyword_search\n- Make edits.\n- If you have completed a standalone chunk of work, make a git commit.\n- Update your todo task list.\n- Repeat.\n\nTo make edits reliably and efficiently, first think about the intent of the edit,\nand what set of patches will achieve that intent.\nThen use the patch tool to make those edits. Combine all edits to any given file into a single patch tool call.\n\nYou may run tool calls in parallel.\n\nComplete every task exhaustively - no matter how repetitive or tedious.\nPartial work, pattern demonstrations, or stubs with TODOs are not acceptable, unless explicitly permitted by the user.\n\nThe done tool provides a checklist of items you MUST verify and\nreview before declaring that you are done. Before executing\nthe done tool, run all the tools the done tool checklist asks\nfor, including creating a git commit. Do not forget to run tests.\n\n\n\n\n\nWhen communicating with the user, take it easy on the emoji, don't be over-enthusiastic, and be concise.\n\nDocker is available. Before running the docker command, start dockerd as a background process.\nAlways use --network=host when running docker containers.\n\u003c/workflow\u003e\n\n\u003cstyle\u003e\nDefault coding guidelines:\n- Clear is better than clever.\n- Minimal inline comments: non-obvious logic and key decisions only.\n- When no commit message style guidance is provided: write a single lowercase line starting with an imperative verb, ≤50 chars, no period\n\u003c/style\u003e\n\n\u003csystem_info\u003e\n\u003cplatform\u003e\nlinux/amd64\n\u003c/platform\u003e\n\u003cpwd\u003e\n/\n\u003c/pwd\u003e\n\u003ccurrent_datetime\u003e\n2025-07-25 19:37:57\n\u003c/current_datetime\u003e\n\u003c/system_info\u003e\n\n\u003cgit_info\u003e\n\u003cgit_root\u003e\n\n\u003c/git_root\u003e\n\u003cHEAD\u003e\nHEAD\n\u003c/HEAD\u003e\n\n\u003c/git_info\u003e\n\n",
550550
"type": "text",
551551
"cache_control": {
552552
"type": "ephemeral"
@@ -557,24 +557,24 @@ Content-Type: application/json
557557
Anthropic-Organization-Id: 3c473a21-7208-450a-a9f8-80aebda45c1b
558558
Anthropic-Ratelimit-Input-Tokens-Limit: 2000000
559559
Anthropic-Ratelimit-Input-Tokens-Remaining: 2000000
560-
Anthropic-Ratelimit-Input-Tokens-Reset: 2025-07-24T23:55:06Z
560+
Anthropic-Ratelimit-Input-Tokens-Reset: 2025-07-25T19:52:15Z
561561
Anthropic-Ratelimit-Output-Tokens-Limit: 400000
562562
Anthropic-Ratelimit-Output-Tokens-Remaining: 400000
563-
Anthropic-Ratelimit-Output-Tokens-Reset: 2025-07-24T23:55:10Z
563+
Anthropic-Ratelimit-Output-Tokens-Reset: 2025-07-25T19:52:20Z
564564
Anthropic-Ratelimit-Requests-Limit: 4000
565565
Anthropic-Ratelimit-Requests-Remaining: 3999
566-
Anthropic-Ratelimit-Requests-Reset: 2025-07-24T23:55:05Z
566+
Anthropic-Ratelimit-Requests-Reset: 2025-07-25T19:52:14Z
567567
Anthropic-Ratelimit-Tokens-Limit: 2400000
568568
Anthropic-Ratelimit-Tokens-Remaining: 2400000
569-
Anthropic-Ratelimit-Tokens-Reset: 2025-07-24T23:55:06Z
569+
Anthropic-Ratelimit-Tokens-Reset: 2025-07-25T19:52:15Z
570570
Cf-Cache-Status: DYNAMIC
571-
Cf-Ray: 964758ac38ba7acd-SJC
571+
Cf-Ray: 964e3251fd2f2523-SJC
572572
Content-Type: application/json
573-
Date: Thu, 24 Jul 2025 23:55:10 GMT
574-
Request-Id: req_011CRSkFtyQxXFGwZsBb7RY3
573+
Date: Fri, 25 Jul 2025 19:52:20 GMT
574+
Request-Id: req_011CRUKYkWzHLghwuujhzGNS
575575
Server: cloudflare
576576
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
577577
Via: 1.1 google
578578
X-Robots-Tag: none
579579

580-
{"id":"msg_01KEJ5q4EwEz9kvMsouiGC9P","type":"message","role":"assistant","model":"claude-sonnet-4-20250514","content":[{"type":"text","text":"Here are the tools available to me:\n\n**File & Code Management:**\n- `bash` - Execute shell commands\n- `keyword_search` - Search files by keywords/concepts\n- `patch` - Modify files with precise text edits\n\n**Task Management:**\n- `think` - Internal note-taking and planning\n- `todo_read` / `todo_write` - Track and manage task lists\n- `done` - Mark completion with checklist verification\n- `codereview` - Run automated code review\n\n**Browser Automation:**\n- `browser_navigate` - Navigate to URLs\n- `browser_click` - Click elements\n- `browser_type` - Type into input fields\n- `browser_wait_for` - Wait for elements\n- `browser_get_text` - Read element text\n- `browser_eval` - Execute JavaScript\n- `browser_scroll_into_view` - Scroll to elements\n- `browser_resize` - Resize browser window\n- `browser_recent_console_logs` - Get console logs\n- `browser_clear_console_logs` - Clear console logs\n- `browser_take_screenshot` - Capture screenshots\n\n**Media:**\n- `read_image` - Read and encode image files\n\n**Help:**\n- `about_sketch` - Get information about Sketch environment"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":4142,"cache_read_input_tokens":0,"output_tokens":296,"service_tier":"standard"}}
580+
{"id":"msg_01GoGZTgeHvh4S9L9RryNM2L","type":"message","role":"assistant","model":"claude-sonnet-4-20250514","content":[{"type":"text","text":"Here are the tools available to me:\n\n**File & Code Management:**\n- `bash` - Execute shell commands\n- `patch` - Modify files with precise text edits\n- `keyword_search` - Search codebase by keywords and concepts\n\n**Task Management:**\n- `todo_read` / `todo_write` - Read and manage task lists\n- `think` - Internal note-taking and planning\n\n**Development Workflow:**\n- `codereview` - Run automated code review\n- `done` - Final checklist before completion\n\n**Browser Automation:**\n- `browser_navigate` - Navigate to URLs\n- `browser_click` - Click elements\n- `browser_type` - Type text into inputs\n- `browser_wait_for` - Wait for elements\n- `browser_get_text` - Read page text\n- `browser_eval` - Execute JavaScript\n- `browser_scroll_into_view` - Scroll to elements\n- `browser_resize` - Resize browser window\n- `browser_recent_console_logs` - Get console logs\n- `browser_clear_console_logs` - Clear console logs\n- `browser_take_screenshot` - Take screenshots\n\n**Utilities:**\n- `read_image` - Read and encode image files\n- `about_sketch` - Get help with Sketch itself"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":4167,"cache_read_input_tokens":0,"output_tokens":299,"service_tier":"standard"}}

0 commit comments

Comments
 (0)