From 6a8833a7b1a6f103b381f0ca6bcb5fbfc8bbaff5 Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Mon, 23 Mar 2026 16:08:25 +0300 Subject: [PATCH] add crypto-monitor SDK example Background agent that checks BTC/ETH prices every 30 minutes via the CoinGecko API and sends desktop notifications through notify-send. Demonstrates long-running autonomous agents with the Kit SDK. --- examples/sdk/README.md | 11 ++++ examples/sdk/crypto-monitor/main.go | 85 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 examples/sdk/crypto-monitor/main.go diff --git a/examples/sdk/README.md b/examples/sdk/README.md index bb713600..7db0b2f9 100644 --- a/examples/sdk/README.md +++ b/examples/sdk/README.md @@ -20,6 +20,17 @@ A minimal script-friendly wrapper that takes a prompt from the command line and go run ./examples/sdk/scripting "Explain what this repo does" ``` +### [crypto-monitor](crypto-monitor/) + +A background agent that checks Bitcoin and Ethereum prices every 30 minutes and sends desktop notifications via `notify-send` (dbus). Demonstrates using the SDK for a long-running autonomous task with a single tool. + +```bash +go run ./examples/sdk/crypto-monitor + +# Override the check interval: +CRYPTO_INTERVAL=5m go run ./examples/sdk/crypto-monitor +``` + ## Getting Started ```go diff --git a/examples/sdk/crypto-monitor/main.go b/examples/sdk/crypto-monitor/main.go new file mode 100644 index 00000000..7b1f3c1f --- /dev/null +++ b/examples/sdk/crypto-monitor/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "os/signal" + "time" + + kit "github.com/mark3labs/kit/pkg/kit" +) + +const systemPrompt = `You are a cryptocurrency price monitor. Your job is to: + +1. Fetch the current prices of Bitcoin and Ethereum using bash with curl +2. Send a desktop notification with the results using notify-send + +To fetch prices, use this CoinGecko API endpoint (no API key needed): + curl -s 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd&include_24hr_change=true' + +To send a desktop notification: + notify-send -i dialog-information "Crypto Prices" "BTC: $XX,XXX (+X.X%)\nETH: $X,XXX (+X.X%)" + +Include the 24h percentage change in the notification. Use a green arrow (▲) for +positive changes and a red arrow (▼) for negative. Format prices with commas. + +If the API call fails, send a notification about the failure instead. + +Always complete both steps: fetch then notify. Be concise — no commentary needed.` + +func main() { + interval := 30 * time.Minute + if os.Getenv("CRYPTO_INTERVAL") != "" { + d, err := time.ParseDuration(os.Getenv("CRYPTO_INTERVAL")) + if err == nil { + interval = d + } + } + + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) + defer cancel() + + host, err := kit.New(ctx, &kit.Options{ + SystemPrompt: systemPrompt, + Tools: []kit.Tool{kit.NewBashTool()}, + NoSession: true, + Quiet: true, + }) + if err != nil { + log.Fatalf("Failed to create kit instance: %v", err) + } + defer func() { _ = host.Close() }() + + fmt.Printf("Crypto price monitor started (every %s)\n", interval) + fmt.Println("Press Ctrl+C to stop") + + // Run immediately on startup, then on each tick. + check(ctx, host) + + ticker := time.NewTicker(interval) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + check(ctx, host) + case <-ctx.Done(): + fmt.Println("\nStopping price monitor") + return + } + } +} + +func check(ctx context.Context, host *kit.Kit) { + fmt.Printf("[%s] Checking prices...\n", time.Now().Format("15:04:05")) + + // Clear session so each check is independent. + host.ClearSession() + + _, err := host.Prompt(ctx, "Fetch current Bitcoin and Ethereum prices and send a desktop notification.") + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + } +}