Skip to content

Commit 7ffb1d6

Browse files
committed
v1.0.1: Add builder pattern methods - WithSystemPrompt, WithModel, WithThinkingLevel, WithMaxTokens, WithTemperature, WithSkills, WithSkillSet, Prompt
1 parent fb73534 commit 7ffb1d6

1 file changed

Lines changed: 151 additions & 8 deletions

File tree

agent.go

Lines changed: 151 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,17 @@ type Event struct {
2929

3030
// Agent is the core reasoning loop.
3131
type Agent struct {
32-
provider Provider
33-
tools map[string]Tool
34-
logger *slog.Logger
35-
Events chan Event
32+
provider Provider
33+
tools map[string]Tool
34+
logger *slog.Logger
35+
Events chan Event
36+
SystemPrompt string
37+
Model string
38+
ThinkingLevel ThinkingLevel
39+
MaxTokens int
40+
Temperature float32
41+
Skills []Skill
42+
Messages []Message
3643
}
3744

3845
// New creates a new Agent.
@@ -42,10 +49,14 @@ func New(p Provider, tools []Tool, logger *slog.Logger) *Agent {
4249
toolMap[t.Name] = t
4350
}
4451
return &Agent{
45-
provider: p,
46-
tools: toolMap,
47-
logger: logger,
48-
Events: make(chan Event, 64),
52+
provider: p,
53+
tools: toolMap,
54+
logger: logger,
55+
Events: make(chan Event, 64),
56+
ThinkingLevel: ThinkingLevelOff,
57+
MaxTokens: 4096,
58+
Temperature: 0.7,
59+
Messages: []Message{},
4960
}
5061
}
5162

@@ -169,3 +180,135 @@ func ToolDescriptions(tools []Tool) string {
169180
}
170181
return sb.String()
171182
}
183+
184+
func (a *Agent) WithSystemPrompt(prompt string) *Agent {
185+
a.SystemPrompt = prompt
186+
return a
187+
}
188+
189+
func (a *Agent) WithModel(model string) *Agent {
190+
a.Model = model
191+
return a
192+
}
193+
194+
func (a *Agent) WithThinkingLevel(level ThinkingLevel) *Agent {
195+
a.ThinkingLevel = level
196+
return a
197+
}
198+
199+
func (a *Agent) WithMaxTokens(maxTokens int) *Agent {
200+
a.MaxTokens = maxTokens
201+
return a
202+
}
203+
204+
func (a *Agent) WithTemperature(temp float32) *Agent {
205+
a.Temperature = temp
206+
return a
207+
}
208+
209+
func (a *Agent) WithSkills(skills []Skill) *Agent {
210+
a.Skills = skills
211+
return a
212+
}
213+
214+
func (a *Agent) WithSkillSet(skillSet *SkillSet) *Agent {
215+
if skillSet != nil {
216+
a.Skills = skillSet.Skills
217+
}
218+
return a
219+
}
220+
221+
func (a *Agent) WithTools(tools []Tool) *Agent {
222+
toolMap := make(map[string]Tool, len(tools))
223+
for _, t := range tools {
224+
toolMap[t.Name] = t
225+
}
226+
a.tools = toolMap
227+
return a
228+
}
229+
230+
func (a *Agent) GetTools() []Tool {
231+
tools := make([]Tool, 0, len(a.tools))
232+
for _, t := range a.tools {
233+
tools = append(tools, t)
234+
}
235+
return tools
236+
}
237+
238+
func (a *Agent) Prompt(ctx context.Context, text string) chan Event {
239+
events := make(chan Event, 64)
240+
go func() {
241+
defer close(events)
242+
events <- Event{Type: "message_start", Content: text}
243+
output, err := a.Run(ctx, a.SystemPrompt, text)
244+
if err != nil {
245+
events <- Event{Type: "error", Content: err.Error()}
246+
} else {
247+
events <- Event{Type: "message_end", Content: output}
248+
}
249+
}()
250+
return events
251+
}
252+
253+
func (a *Agent) PromptMessages(ctx context.Context, messages []Message) chan Event {
254+
events := make(chan Event, 64)
255+
go func() {
256+
defer close(events)
257+
allTools := a.GetTools()
258+
systemContent := a.SystemPrompt
259+
if systemContent != "" {
260+
systemContent += "\n\n"
261+
}
262+
systemContent += ToolDescriptions(allTools)
263+
264+
fullMessages := []Message{{Role: "system", Content: systemContent}}
265+
fullMessages = append(fullMessages, messages...)
266+
267+
events <- Event{Type: "message_start", Content: ""}
268+
269+
for i := 0; i < 20; i++ {
270+
events <- Event{Type: "turn_start", Content: fmt.Sprintf("turn %d", i+1)}
271+
272+
response, err := a.provider.Complete(ctx, fullMessages)
273+
if err != nil {
274+
events <- Event{Type: "error", Content: err.Error()}
275+
break
276+
}
277+
278+
events <- Event{Type: "content", Content: response}
279+
280+
fullMessages = append(fullMessages, Message{Role: "assistant", Content: response})
281+
282+
calls := ParseToolCalls(response)
283+
if len(calls) == 0 {
284+
events <- Event{Type: "message_end", Content: response}
285+
break
286+
}
287+
288+
var toolResults strings.Builder
289+
for _, call := range calls {
290+
tool, ok := a.tools[call.Tool]
291+
if !ok {
292+
result := fmt.Sprintf("unknown tool: %s", call.Tool)
293+
toolResults.WriteString(fmt.Sprintf("Tool %s: %s\n", call.Tool, result))
294+
events <- Event{Type: "tool_result", Content: result}
295+
continue
296+
}
297+
298+
events <- Event{Type: "tool_execution_start", Content: call.Tool}
299+
300+
result, err := tool.Execute(ctx, call.Args)
301+
if err != nil {
302+
result = fmt.Sprintf("ERROR: %s\nOutput: %s", err.Error(), result)
303+
}
304+
305+
events <- Event{Type: "tool_execution_end", Content: result}
306+
toolResults.WriteString(fmt.Sprintf("Tool %s result:\n%s\n\n", call.Tool, result))
307+
}
308+
309+
fullMessages = append(fullMessages, Message{Role: "user", Content: toolResults.String()})
310+
events <- Event{Type: "turn_end", Content: ""}
311+
}
312+
}()
313+
return events
314+
}

0 commit comments

Comments
 (0)