# Example Tutorials Step-by-step tutorials for building agents with AgentKit URL: https://agentkit.tech/docs/examples/examples.mdx Learn AgentKit through detailed tutorials that walk you through building different types of agents. Each tutorial includes complete code examples, explanations, and best practices. ## Tutorial 1: Simple Agent Build your first agent with basic tools and understand core concepts. ### Overview Create an agent that can: * Greet users by name * Perform basic calculations * Handle multiple tools intelligently ### Step 1: Setup and Dependencies ```go package main import ( "context" "fmt" "log" "os" "github.com/model-box/agent-kit/agent" "github.com/model-box/agent-kit/common" "github.com/model-box/agent-kit/model" "github.com/model-box/agent-kit/session" "github.com/model-box/agent-kit/tool" ) ``` ### Step 2: Define Tool Input Structures ```go // GreetingInput defines the input for the greeting tool type GreetingInput struct { Name string `json:"name" jsonschema:"description=The name of the person to greet"` } // CalculatorInput defines the input for the calculator tool type CalculatorInput struct { Operation string `json:"operation" jsonschema:"description=The operation to perform (add, subtract, multiply, divide)"` A float64 `json:"a" jsonschema:"description=The first number"` B float64 `json:"b" jsonschema:"description=The second number"` } ``` ### Step 3: Implement Tool Handlers ```go // greetingHandler implements the greeting functionality func greetingHandler(ctx common.RunContext, params GreetingInput) (string, error) { return fmt.Sprintf("Hello, %s! Nice to meet you!", params.Name), nil } // calculateHandler implements basic math operations func calculateHandler(ctx common.RunContext, params CalculatorInput) (string, error) { var result float64 switch params.Operation { case "add": result = params.A + params.B case "subtract": result = params.A - params.B case "multiply": result = params.A * params.B case "divide": if params.B == 0 { return "", fmt.Errorf("division by zero") } result = params.A / params.B default: return "", fmt.Errorf("unsupported operation: %s", params.Operation) } return fmt.Sprintf("%.2f", result), nil } ``` ### Step 4: Create the Agent ```go func main() { // Get API key from environment apiKey := os.Getenv("OPENAI_API_KEY") if apiKey == "" { log.Fatal("OPENAI_API_KEY environment variable is required") } // Create model with configuration model := model.Model("gpt-4o"). SetAPIKey(apiKey). SetTemperature(0.1). // Low temperature for consistent responses SetMaxTokens(1000) // Reasonable token limit // Create tools greetingTool := tool.NewFunctionTool( "greeting", "Greet a person by name", greetingHandler, ) calculatorTool := tool.NewFunctionTool( "calculator", "Perform basic math operations (add, subtract, multiply, divide)", calculateHandler, ) // Create agent with tools agent := agent.New(). SetModel(model). SetSystemPrompt("You are a helpful assistant with access to greeting and calculator tools. Use tools when appropriate to help users."). AddTool(greetingTool). AddTool(calculatorTool) // Test the agent testCases := []string{ "Hello, can you greet me? My name is Alice", "What is 15 + 27?", "Can you calculate 144 divided by 12?", "Please greet Bob and then calculate 5 * 8", } for i, testCase := range testCases { fmt.Printf("\n--- Test Case %d ---\n", i+1) fmt.Printf("Input: %s\n", testCase) fmt.Printf("Output: ") // Run with session session := session.New(agent) result, err := session.Run(context.Background(), []agent.ChatMessage{ agent.NewUserMessage(testCase), }, nil) if err != nil { fmt.Printf("Error: %v\n", err) continue } fmt.Println(result.FinalOutput) } } ``` ### Key Concepts Explained 1. **Model Configuration**: Set temperature and token limits appropriate for your use case 2. **Tool Design**: Define clear input structures with JSON schema descriptions 3. **Error Handling**: Always handle errors gracefully in tool handlers 4. **Agent Configuration**: Use descriptive system prompts that mention available tools 5. **Session Usage**: Use sessions for stateful conversations ## Tutorial 2: Streaming Agent with Sessions Build an agent that provides real-time streaming responses and maintains conversation history. ### Overview This tutorial covers: * Real-time streaming responses * Session-based conversation memory * Advanced tool usage * Event handling patterns ### Step 1: Advanced Tool Implementation ```go type CalculatorInput struct { Operation string `json:"operation" jsonschema:"enum=add,enum=subtract,enum=multiply,enum=divide,enum=sqrt,enum=power"` A float64 `json:"a" jsonschema:"description=First number"` B *float64 `json:"b,omitempty" jsonschema:"description=Second number (not needed for sqrt)"` } func calculatorTool(ctx common.RunContext, input CalculatorInput) (string, error) { fmt.Printf("šŸ”§ Calculator tool called with: %+v\n", input) switch input.Operation { case "add": if input.B == nil { return "", fmt.Errorf("operation 'add' requires both a and b") } result := input.A + *input.B return fmt.Sprintf("%.2f", result), nil case "sqrt": if input.A < 0 { return "", fmt.Errorf("cannot calculate square root of negative number") } result := math.Sqrt(input.A) return fmt.Sprintf("%.2f", result), nil case "power": if input.B == nil { return "", fmt.Errorf("operation 'power' requires both a and b") } result := math.Pow(input.A, *input.B) return fmt.Sprintf("%.2f", result), nil // ... other operations } return "", fmt.Errorf("unsupported operation: %s", input.Operation) } ``` ### Step 2: Streaming Implementation ```go func runStreamingExample(agent *agent.Agent) { // Create session for conversation state sess := session.New(agent) inputs := []string{ "Hi! I'm learning about math. Can you help me?", "What's the square root of 144?", "Now calculate 12 to the power of 2", "Perfect! What's 12 * 12 + 10?", } for i, input := range inputs { fmt.Printf("\n=== Conversation Turn %d ===\n", i+1) fmt.Printf("šŸ‘¤ User: %s\n", input) fmt.Printf("šŸ¤– Assistant: ") // Start streaming stream, err := sess.RunStreamed(context.Background(), []agent.ChatMessage{ agent.NewUserMessage(input), }, nil) if err != nil { fmt.Printf("Error: %v\n", err) continue } // Process streaming events for event, err := range stream.StreamEvents() { if err != nil { fmt.Printf("\nStream error: %v\n", err) break } switch { case event.IsTextDelta(): // Print each text chunk as it arrives fmt.Print(event.GetContent()) case event.IsCompleted(): fmt.Println("\nāœ… Response completed!") break } } // Small delay between conversations time.Sleep(1 * time.Second) } } ``` ### Step 3: Complete Streaming Agent ```go func main() { apiKey := os.Getenv("OPENAI_API_KEY") if apiKey == "" { log.Fatal("OPENAI_API_KEY environment variable is required") } fmt.Println("šŸš€ AgentKit Streaming Session Example") fmt.Println("=====================================") // Create model with streaming-optimized settings model := model.Model("gpt-4o"). SetAPIKey(apiKey). SetTemperature(0.3). // Balanced creativity SetMaxTokens(800) // Reasonable for conversations // Create advanced calculator tool calcTool := tool.NewFunctionTool( "advanced_calculator", "Perform mathematical operations including basic arithmetic, square root, and power", calculatorTool, ) // Create agent optimized for conversations agent := agent.New(). SetModel(model). SetSystemPrompt(`You are a friendly and helpful math tutor. You have access to an advanced calculator tool for mathematical operations. Guidelines: - Use the calculator for any mathematical computations - Explain your reasoning step by step - Be encouraging and supportive - Build on previous conversation context`). AddTool(calcTool) // Run streaming example runStreamingExample(agent) fmt.Println("\nšŸŽ“ Math tutoring session completed!") } ``` ### Key Streaming Concepts 1. **Event Types**: Handle different event types (`IsTextDelta()`, `IsCompleted()`) 2. **Real-time Output**: Print chunks immediately for responsive UX 3. **Session Continuity**: Sessions maintain context across streaming calls 4. **Error Handling**: Handle both setup errors and streaming errors 5. **Event Loop**: Use range over `StreamEvents()` for clean iteration ## Tutorial 3: Business Agent (Sales Assistant) Build a production-ready sales agent with lead qualification and business logic. ### Overview Create a sophisticated sales agent that: * Qualifies leads using BANT methodology * Provides product information and pricing * Handles objections professionally * Maintains sales conversation flow ### Step 1: Business Logic Implementation ```go // LeadQualificationInput for BANT analysis type LeadQualificationInput struct { CompanySize string `json:"company_size" jsonschema:"description=Number of employees or company size indicator"` Industry string `json:"industry" jsonschema:"description=Industry or business vertical"` CurrentSolution string `json:"current_solution,omitempty" jsonschema:"description=Current tools or solutions they use"` Budget string `json:"budget,omitempty" jsonschema:"description=Budget range or procurement process"` Timeline string `json:"timeline,omitempty" jsonschema:"description=Implementation timeline or urgency"` Authority string `json:"authority,omitempty" jsonschema:"description=Decision making role or influence"` } func leadQualificationTool(ctx common.RunContext, input LeadQualificationInput) (string, error) { // Implement BANT scoring logic score := 0 feedback := []string{} // Budget assessment if strings.Contains(strings.ToLower(input.Budget), "budget") || strings.Contains(strings.ToLower(input.Budget), "$") { score += 25 feedback = append(feedback, "āœ… Budget: Expressed budget awareness") } else { feedback = append(feedback, "āš ļø Budget: Needs budget qualification") } // Authority assessment if strings.Contains(strings.ToLower(input.Authority), "decision") || strings.Contains(strings.ToLower(input.Authority), "manager") || strings.Contains(strings.ToLower(input.Authority), "director") { score += 25 feedback = append(feedback, "āœ… Authority: Has decision making influence") } else { feedback = append(feedback, "āš ļø Authority: May need to involve decision makers") } // Need assessment if input.CurrentSolution != "" { score += 25 feedback = append(feedback, "āœ… Need: Has existing solution (replacement opportunity)") } else { feedback = append(feedback, "āœ… Need: Greenfield opportunity") score += 20 } // Timeline assessment if strings.Contains(strings.ToLower(input.Timeline), "urgent") || strings.Contains(strings.ToLower(input.Timeline), "asap") || strings.Contains(strings.ToLower(input.Timeline), "month") { score += 25 feedback = append(feedback, "āœ… Timeline: Urgent implementation need") } else if input.Timeline != "" { score += 15 feedback = append(feedback, "āš ļø Timeline: Has timeline but not urgent") } // Generate qualification summary var qualification string switch { case score >= 80: qualification = "šŸ”„ HOT LEAD - High priority follow-up recommended" case score >= 60: qualification = "🌟 WARM LEAD - Good opportunity, continue qualification" case score >= 40: qualification = "šŸ”„ DEVELOPING LEAD - Needs further nurturing" default: qualification = "ā„ļø COLD LEAD - Early stage, focus on education" } result := fmt.Sprintf(`BANT Qualification Score: %d/100 %s %s Company Profile: - Size: %s - Industry: %s - Current Solution: %s Next Steps: %s`, score, qualification, strings.Join(feedback, "\n"), input.CompanySize, input.Industry, input.CurrentSolution, getNextStepsRecommendation(score)) return result, nil } func getNextStepsRecommendation(score int) string { switch { case score >= 80: return "Schedule demo, prepare custom proposal, involve technical team" case score >= 60: return "Continue discovery call, identify key stakeholders, share case studies" case score >= 40: return "Provide educational content, schedule follow-up, build relationship" default: return "Share general resources, add to nurture campaign, quarterly check-in" } } ``` ### Step 2: Product Information Tool ```go type ProductInfoInput struct { ProductArea string `json:"product_area" jsonschema:"description=Product area of interest (project-management, analytics, integrations, security)"` CompanySize string `json:"company_size" jsonschema:"description=Company size for appropriate recommendations"` } func productInfoTool(ctx common.RunContext, input ProductInfoInput) (string, error) { products := map[string]map[string]string{ "project-management": { "small": "AgentKit Starter: $29/user/month - Perfect for small teams with basic project tracking", "medium": "AgentKit Professional: $49/user/month - Advanced workflows, custom fields, reporting", "large": "AgentKit Enterprise: $89/user/month - Advanced security, SSO, unlimited everything", "enterprise": "AgentKit Enterprise+: Custom pricing - White-label options, dedicated support", }, "analytics": { "small": "Basic Analytics: Included in Professional+ plans", "medium": "Advanced Analytics: $19/user/month add-on - Custom dashboards, exports", "large": "Analytics Suite: $39/user/month - Real-time insights, ML predictions", "enterprise": "Enterprise Analytics: Custom pricing - Data warehouse integration, API access", }, } sizeCategory := categorizeSizeForPricing(input.CompanySize) if productMap, exists := products[input.ProductArea]; exists { if price, exists := productMap[sizeCategory]; exists { return fmt.Sprintf(`Product Recommendation for %s (%s company): %s Key Features: %s Would you like me to schedule a personalized demo to show these features in action?`, input.ProductArea, input.CompanySize, price, getKeyFeatures(input.ProductArea, sizeCategory)), nil } } return "I'd be happy to provide detailed product information. Could you specify which area you're most interested in: project management, analytics, integrations, or security?", nil } func categorizeSizeForPricing(companySize string) string { size := strings.ToLower(companySize) switch { case strings.Contains(size, "1-") || strings.Contains(size, "startup") || strings.Contains(size, "small"): return "small" case strings.Contains(size, "50") || strings.Contains(size, "medium") || strings.Contains(size, "100"): return "medium" case strings.Contains(size, "500") || strings.Contains(size, "large") || strings.Contains(size, "1000"): return "large" default: return "enterprise" } } ``` ### Step 3: Complete Sales Agent ```go func main() { apiKey := os.Getenv("OPENAI_API_KEY") if apiKey == "" { log.Fatal("OPENAI_API_KEY environment variable is required") } fmt.Println("šŸ’¼ AgentKit Sales Agent Example") fmt.Println("===============================") // Create model optimized for sales conversations model := model.Model("gpt-4o"). SetAPIKey(apiKey). SetTemperature(0.7). // Higher temperature for personable conversations SetMaxTokens(1200) // Longer responses for detailed explanations // Create sales tools qualificationTool := tool.NewFunctionTool( "bant_qualification", "Qualify leads using BANT methodology (Budget, Authority, Need, Timeline)", leadQualificationTool, ) productTool := tool.NewFunctionTool( "product_information", "Provide product information and pricing based on company needs", productInfoTool, ) // Create sales agent agent := agent.New(). SetModel(model). SetSystemPrompt(`You are a professional and friendly sales representative for AgentKit, a comprehensive business automation platform. Your Role: 1. Engage prospects in meaningful conversations about their business needs 2. Qualify leads using BANT methodology (Budget, Authority, Need, Timeline) 3. Provide relevant product information and pricing 4. Handle objections professionally and empathetically 5. Guide prospects through the sales process 6. Build trust and rapport with potential customers Approach: - Be consultative, not pushy - Ask discovery questions to understand their specific challenges - Listen actively and provide relevant solutions - Use tools to provide accurate qualification and product information - Always focus on solving their problems, not just selling products Tools Available: - BANT Qualification: Use when you have enough information about budget, authority, need, and timeline - Product Information: Use when prospects ask about specific features, pricing, or recommendations`). AddTool(qualificationTool). AddTool(productTool) // Sales scenarios for testing scenarios := []string{ "Hi, I'm interested in your software solution for my small business. We have about 25 employees and are looking for a project management tool.", "I saw your ad online and want to know more about pricing for enterprise customers. We're a 500-person company in the healthcare industry.", "We're currently using a competitor's product but aren't happy with it. Can you tell me how your solution compares?", "I'm evaluating different vendors for our Q2 budget. What's your best price for a 100-user license?", } // Run sales conversations for i, scenario := range scenarios { fmt.Printf("\n=== Sales Scenario %d ===\n", i+1) fmt.Printf("šŸ‘¤ Prospect: %s\n", scenario) fmt.Printf("šŸ’¼ Sales Agent: ") session := session.New(agent) // Use streaming for more natural sales conversations stream, err := session.RunStreamed(context.Background(), []agent.ChatMessage{ agent.NewUserMessage(scenario), }, nil) if err != nil { fmt.Printf("Error: %v\n", err) continue } for event, err := range stream.StreamEvents() { if err != nil { break } if event.IsTextDelta() { fmt.Print(event.GetContent()) } } fmt.Println("\n") } fmt.Println("šŸŽÆ Sales scenarios completed!") } ``` ### Business Agent Best Practices 1. **Domain-Specific Prompts**: Tailor system prompts to specific business roles 2. **Business Logic Tools**: Implement real business processes (BANT, pricing, etc.) 3. **Professional Tone**: Higher temperature for natural, personable conversations 4. **Comprehensive Responses**: Longer token limits for detailed business discussions 5. **Industry Knowledge**: Build in relevant industry context and terminology ## Key Takeaways ### Development Patterns 1. **Start Simple**: Begin with basic tools and gradually add complexity 2. **Use Sessions**: Always use sessions for stateful conversations 3. **Handle Errors**: Implement comprehensive error handling 4. **Stream Responses**: Use streaming for better user experience 5. **Test Thoroughly**: Test with various scenarios and edge cases ### Production Considerations 1. **API Key Management**: Never hardcode keys, always use environment variables 2. **Rate Limiting**: Implement appropriate limits for production usage 3. **Monitoring**: Add logging and metrics for production systems 4. **Security**: Validate inputs and sanitize outputs 5. **Scalability**: Consider session management for concurrent users ### Tool Design 1. **Clear Schemas**: Use descriptive JSON schema annotations 2. **Validation**: Validate inputs in tool handlers 3. **Error Messages**: Provide helpful error messages 4. **Business Logic**: Implement real business processes, not just demos 5. **Testing**: Test tools independently before integration These tutorials provide a solid foundation for building sophisticated agents with AgentKit. Use them as starting points and adapt the patterns to your specific use cases.