Skip to content

Commit 2aae7f7

Browse files
authored
Merge pull request sipeed#78 from SatyamDevv/main
feat(search): Add DuckDuckGo fallback for credit-card-free web search
2 parents 092d2f0 + 878889b commit 2aae7f7

5 files changed

Lines changed: 311 additions & 140 deletions

File tree

README.md

Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@
6868

6969
🤖 **AI-Bootstrapped**: Autonomous Go-native implementation — 95% Agent-generated core with human-in-the-loop refinement.
7070

71-
| | OpenClaw | NanoBot | **PicoClaw** |
72-
| --- | --- | --- |--- |
73-
| **Language** | TypeScript | Python | **Go** |
74-
| **RAM** | >1GB |>100MB| **< 10MB** |
75-
| **Startup**</br>(0.8GHz core) | >500s | >30s | **<1s** |
76-
| **Cost** | Mac Mini 599$ | Most Linux SBC </br>~50$ |**Any Linux Board**</br>**As low as 10$** |
71+
| | OpenClaw | NanoBot | **PicoClaw** |
72+
| ----------------------------- | ------------- | ------------------------ | ----------------------------------------- |
73+
| **Language** | TypeScript | Python | **Go** |
74+
| **RAM** | >1GB | >100MB | **< 10MB** |
75+
| **Startup**</br>(0.8GHz core) | >500s | >30s | **<1s** |
76+
| **Cost** | Mac Mini 599$ | Most Linux SBC </br>~50$ | **Any Linux Board**</br>**As low as 10$** |
7777

7878
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
7979

@@ -103,7 +103,7 @@
103103

104104
PicoClaw can be deployed on almost any Linux device!
105105

106-
- $9.9 [LicheeRV-Nano](https://www.aliexpress.com/item/1005006519668532.html) E(Ethernet) or W(WiFi6) version, for Minimal Home Assistant
106+
- $9.9 [LicheeRV-Nano](https://www.aliexpress.com/item/1005006519668532.html) E(Ethernet) or W(WiFi6) version, for Minimal Home Assistant
107107
- $30~50 [NanoKVM](https://www.aliexpress.com/item/1005007369816019.html), or $100 [NanoKVM-Pro](https://www.aliexpress.com/item/1005010048471263.html) for Automated Server Maintenance
108108
- $50 [MaixCAM](https://www.aliexpress.com/item/1005008053333693.html) or $100 [MaixCAM2](https://www.kickstarter.com/projects/zepan/maixcam2-build-your-next-gen-4k-ai-camera) for Smart Monitoring
109109

@@ -180,7 +180,7 @@ docker compose --profile gateway up -d
180180
> [!TIP]
181181
> Set your API key in `~/.picoclaw/config.json`.
182182
> Get API keys: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM)
183-
> Web search is **optional** - get free [Brave Search API](https://brave.com/search/api) (2000 free queries/month)
183+
> Web search is **optional** - get free [Brave Search API](https://brave.com/search/api) (2000 free queries/month) or use built-in auto fallback.
184184
185185
**1. Initialize**
186186

@@ -209,9 +209,14 @@ picoclaw onboard
209209
},
210210
"tools": {
211211
"web": {
212-
"search": {
212+
"brave": {
213+
"enabled": false,
213214
"api_key": "YOUR_BRAVE_API_KEY",
214215
"max_results": 5
216+
},
217+
"duckduckgo": {
218+
"enabled": true,
219+
"max_results": 5
215220
}
216221
}
217222
}
@@ -239,12 +244,12 @@ That's it! You have a working AI assistant in 2 minutes.
239244

240245
Talk to your picoclaw through Telegram, Discord, or DingTalk
241246

242-
| Channel | Setup |
243-
|---------|-------|
244-
| **Telegram** | Easy (just a token) |
245-
| **Discord** | Easy (bot token + intents) |
246-
| **QQ** | Easy (AppID + AppSecret) |
247-
| **DingTalk** | Medium (app credentials) |
247+
| Channel | Setup |
248+
| ------------ | -------------------------- |
249+
| **Telegram** | Easy (just a token) |
250+
| **Discord** | Easy (bot token + intents) |
251+
| **QQ** | Easy (AppID + AppSecret) |
252+
| **DingTalk** | Medium (app credentials) |
248253

249254
<details>
250255
<summary><b>Telegram</b> (Recommended)</summary>
@@ -400,8 +405,6 @@ Connect Picoclaw to the Agent Social Network simply by sending a single message
400405

401406
**Read `https://clawdchat.ai/skill.md` and follow the instructions to join [ClawdChat.ai](https://clawdchat.ai)**
402407

403-
404-
405408
## ⚙️ Configuration
406409

407410
Config file: `~/.picoclaw/config.json`
@@ -598,15 +601,15 @@ The subagent has access to tools (message, web_search, etc.) and can communicate
598601
> [!NOTE]
599602
> Groq provides free voice transcription via Whisper. If configured, Telegram voice messages will be automatically transcribed.
600603
601-
| Provider | Purpose | Get API Key |
602-
|----------|---------|-------------|
603-
| `gemini` | LLM (Gemini direct) | [aistudio.google.com](https://aistudio.google.com) |
604-
| `zhipu` | LLM (Zhipu direct) | [bigmodel.cn](bigmodel.cn) |
605-
| `openrouter(To be tested)` | LLM (recommended, access to all models) | [openrouter.ai](https://openrouter.ai) |
606-
| `anthropic(To be tested)` | LLM (Claude direct) | [console.anthropic.com](https://console.anthropic.com) |
607-
| `openai(To be tested)` | LLM (GPT direct) | [platform.openai.com](https://platform.openai.com) |
608-
| `deepseek(To be tested)` | LLM (DeepSeek direct) | [platform.deepseek.com](https://platform.deepseek.com) |
609-
| `groq` | LLM + **Voice transcription** (Whisper) | [console.groq.com](https://console.groq.com) |
604+
| Provider | Purpose | Get API Key |
605+
| -------------------------- | --------------------------------------- | ------------------------------------------------------ |
606+
| `gemini` | LLM (Gemini direct) | [aistudio.google.com](https://aistudio.google.com) |
607+
| `zhipu` | LLM (Zhipu direct) | [bigmodel.cn](bigmodel.cn) |
608+
| `openrouter(To be tested)` | LLM (recommended, access to all models) | [openrouter.ai](https://openrouter.ai) |
609+
| `anthropic(To be tested)` | LLM (Claude direct) | [console.anthropic.com](https://console.anthropic.com) |
610+
| `openai(To be tested)` | LLM (GPT direct) | [platform.openai.com](https://platform.openai.com) |
611+
| `deepseek(To be tested)` | LLM (DeepSeek direct) | [platform.deepseek.com](https://platform.deepseek.com) |
612+
| `groq` | LLM + **Voice transcription** (Whisper) | [console.groq.com](https://console.groq.com) |
610613

611614
<details>
612615
<summary><b>Zhipu</b></summary>
@@ -632,8 +635,8 @@ The subagent has access to tools (message, web_search, etc.) and can communicate
632635
"zhipu": {
633636
"api_key": "Your API Key",
634637
"api_base": "https://open.bigmodel.cn/api/paas/v4"
635-
},
636-
},
638+
}
639+
}
637640
}
638641
```
639642

@@ -694,8 +697,14 @@ picoclaw agent -m "Hello"
694697
},
695698
"tools": {
696699
"web": {
697-
"search": {
698-
"api_key": "BSA..."
700+
"brave": {
701+
"enabled": false,
702+
"api_key": "BSA...",
703+
"max_results": 5
704+
},
705+
"duckduckgo": {
706+
"enabled": true,
707+
"max_results": 5
699708
}
700709
}
701710
},
@@ -710,15 +719,15 @@ picoclaw agent -m "Hello"
710719

711720
## CLI Reference
712721

713-
| Command | Description |
714-
|---------|-------------|
715-
| `picoclaw onboard` | Initialize config & workspace |
716-
| `picoclaw agent -m "..."` | Chat with the agent |
717-
| `picoclaw agent` | Interactive chat mode |
718-
| `picoclaw gateway` | Start the gateway |
719-
| `picoclaw status` | Show status |
720-
| `picoclaw cron list` | List all scheduled jobs |
721-
| `picoclaw cron add ...` | Add a scheduled job |
722+
| Command | Description |
723+
| ------------------------- | ----------------------------- |
724+
| `picoclaw onboard` | Initialize config & workspace |
725+
| `picoclaw agent -m "..."` | Chat with the agent |
726+
| `picoclaw agent` | Interactive chat mode |
727+
| `picoclaw gateway` | Start the gateway |
728+
| `picoclaw status` | Show status |
729+
| `picoclaw cron list` | List all scheduled jobs |
730+
| `picoclaw cron add ...` | Add a scheduled job |
722731

723732
### Scheduled Tasks / Reminders
724733

@@ -752,21 +761,28 @@ This is normal if you haven't configured a search API key yet. PicoClaw will pro
752761

753762
To enable web search:
754763

755-
1. Get a free API key at [https://brave.com/search/api](https://brave.com/search/api) (2000 free queries/month)
756-
2. Add to `~/.picoclaw/config.json`:
757-
758-
```json
759-
{
760-
"tools": {
761-
"web": {
762-
"search": {
763-
"api_key": "YOUR_BRAVE_API_KEY",
764-
"max_results": 5
765-
}
766-
}
767-
}
768-
}
769-
```
764+
1. **Option 1 (Recommended)**: Get a free API key at [https://brave.com/search/api](https://brave.com/search/api) (2000 free queries/month) for the best results.
765+
2. **Option 2 (No Credit Card)**: If you don't have a key, we automatically fall back to **DuckDuckGo** (no key required).
766+
767+
Add the key to `~/.picoclaw/config.json` if using Brave:
768+
769+
```json
770+
{
771+
"tools": {
772+
"web": {
773+
"brave": {
774+
"enabled": false,
775+
"api_key": "YOUR_BRAVE_API_KEY",
776+
"max_results": 5
777+
},
778+
"duckduckgo": {
779+
"enabled": true,
780+
"max_results": 5
781+
}
782+
}
783+
}
784+
}
785+
```
770786

771787
### Getting content filtering errors
772788

@@ -780,9 +796,9 @@ This happens when another instance of the bot is running. Make sure only one `pi
780796

781797
## 📝 API Key Comparison
782798

783-
| Service | Free Tier | Use Case |
784-
|---------|-----------|-----------|
785-
| **OpenRouter** | 200K tokens/month | Multiple models (Claude, GPT-4, etc.) |
786-
| **Zhipu** | 200K tokens/month | Best for Chinese users |
787-
| **Brave Search** | 2000 queries/month | Web search functionality |
788-
| **Groq** | Free tier available | Fast inference (Llama, Mixtral) |
799+
| Service | Free Tier | Use Case |
800+
| ---------------- | ------------------- | ------------------------------------- |
801+
| **OpenRouter** | 200K tokens/month | Multiple models (Claude, GPT-4, etc.) |
802+
| **Zhipu** | 200K tokens/month | Best for Chinese users |
803+
| **Brave Search** | 2000 queries/month | Web search functionality |
804+
| **Groq** | Free tier available | Fast inference (Llama, Mixtral) |

pkg/agent/loop.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,15 @@ func createToolRegistry(workspace string, restrict bool, cfg *config.Config, msg
7070
// Shell execution
7171
registry.Register(tools.NewExecTool(workspace, restrict))
7272

73-
// Web tools
74-
braveAPIKey := cfg.Tools.Web.Search.APIKey
75-
registry.Register(tools.NewWebSearchTool(braveAPIKey, cfg.Tools.Web.Search.MaxResults))
73+
if searchTool := tools.NewWebSearchTool(tools.WebSearchToolOptions{
74+
BraveAPIKey: cfg.Tools.Web.Brave.APIKey,
75+
BraveMaxResults: cfg.Tools.Web.Brave.MaxResults,
76+
BraveEnabled: cfg.Tools.Web.Brave.Enabled,
77+
DuckDuckGoMaxResults: cfg.Tools.Web.DuckDuckGo.MaxResults,
78+
DuckDuckGoEnabled: cfg.Tools.Web.DuckDuckGo.Enabled,
79+
}); searchTool != nil {
80+
registry.Register(searchTool)
81+
}
7682
registry.Register(tools.NewWebFetchTool(50000))
7783

7884
// Message tool - available to both agent and subagent

pkg/config/config.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,20 @@ type GatewayConfig struct {
164164
Port int `json:"port" env:"PICOCLAW_GATEWAY_PORT"`
165165
}
166166

167-
type WebSearchConfig struct {
168-
APIKey string `json:"api_key" env:"PICOCLAW_TOOLS_WEB_SEARCH_API_KEY"`
169-
MaxResults int `json:"max_results" env:"PICOCLAW_TOOLS_WEB_SEARCH_MAX_RESULTS"`
167+
type BraveConfig struct {
168+
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_BRAVE_ENABLED"`
169+
APIKey string `json:"api_key" env:"PICOCLAW_TOOLS_WEB_BRAVE_API_KEY"`
170+
MaxResults int `json:"max_results" env:"PICOCLAW_TOOLS_WEB_BRAVE_MAX_RESULTS"`
171+
}
172+
173+
type DuckDuckGoConfig struct {
174+
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_DUCKDUCKGO_ENABLED"`
175+
MaxResults int `json:"max_results" env:"PICOCLAW_TOOLS_WEB_DUCKDUCKGO_MAX_RESULTS"`
170176
}
171177

172178
type WebToolsConfig struct {
173-
Search WebSearchConfig `json:"search"`
179+
Brave BraveConfig `json:"brave"`
180+
DuckDuckGo DuckDuckGoConfig `json:"duckduckgo"`
174181
}
175182

176183
type ToolsConfig struct {
@@ -257,10 +264,15 @@ func DefaultConfig() *Config {
257264
},
258265
Tools: ToolsConfig{
259266
Web: WebToolsConfig{
260-
Search: WebSearchConfig{
267+
Brave: BraveConfig{
268+
Enabled: false,
261269
APIKey: "",
262270
MaxResults: 5,
263271
},
272+
DuckDuckGo: DuckDuckGoConfig{
273+
Enabled: true,
274+
MaxResults: 5,
275+
},
264276
},
265277
},
266278
Heartbeat: HeartbeatConfig{

pkg/migrate/config.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,17 @@ func ConvertConfig(data map[string]interface{}) (*config.Config, []string, error
212212

213213
if tools, ok := getMap(data, "tools"); ok {
214214
if web, ok := getMap(tools, "web"); ok {
215+
// Migrate old "search" config to "brave" if api_key is present
215216
if search, ok := getMap(web, "search"); ok {
216217
if v, ok := getString(search, "api_key"); ok {
217-
cfg.Tools.Web.Search.APIKey = v
218+
cfg.Tools.Web.Brave.APIKey = v
219+
if v != "" {
220+
cfg.Tools.Web.Brave.Enabled = true
221+
}
218222
}
219223
if v, ok := getFloat(search, "max_results"); ok {
220-
cfg.Tools.Web.Search.MaxResults = int(v)
224+
cfg.Tools.Web.Brave.MaxResults = int(v)
225+
cfg.Tools.Web.DuckDuckGo.MaxResults = int(v)
221226
}
222227
}
223228
}
@@ -271,8 +276,8 @@ func MergeConfig(existing, incoming *config.Config) *config.Config {
271276
existing.Channels.MaixCam = incoming.Channels.MaixCam
272277
}
273278

274-
if existing.Tools.Web.Search.APIKey == "" {
275-
existing.Tools.Web.Search = incoming.Tools.Web.Search
279+
if existing.Tools.Web.Brave.APIKey == "" {
280+
existing.Tools.Web.Brave = incoming.Tools.Web.Brave
276281
}
277282

278283
return existing

0 commit comments

Comments
 (0)