Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4129,3 +4129,27 @@ export function CursorIcon(props: SVGProps<SVGSVGElement>) {
</svg>
)
}

export function DuckDuckGoIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='-108 -108 216 216'>
<circle r='108' fill='#d53' />
<circle r='96' fill='none' stroke='#ffffff' stroke-width='7' />
<path
d='M-32-55C-62-48-51-6-51-6l19 93 7 3M-39-73h-8l11 4s-11 0-11 7c24-1 35 5 35 5'
fill='#ddd'
/>
<path d='M25 95S1 57 1 32c0-47 31-7 31-44S1-58 1-58c-15-19-44-15-44-15l7 4s-7 2-9 4 19-3 28 5c-37 3-31 33-31 33l21 120' />
<path d='M25-1l38-10c34 5-29 24-33 23C0 7 9 32 45 24s9 20-24 9C-26 20-1-3 25-1' fill='#fc0' />
<path
d='M15 78l2-3c22 8 23 11 22-9s0-20-23-3c0-5-13-3-15 0-21-9-23-12-22 2 2 29 1 24 21 14'
fill='#6b5'
/>
<path d='M-1 67v12c1 2 17 2 17-2s-8 3-13 1-2-13-2-13' fill='#4a4' />
<path
d='M-23-32c-5-6-18-1-15 7 1-4 8-10 15-7m32 0c1-6 11-7 14-1-4-2-10-2-14 1m-33 16a2 2 0 1 1 0 1m-8 3a7 7 0 1 0 0-1m52-6a2 2 0 1 1 0 1m-6 3a6 6 0 1 0 0-1'
fill='#148'
/>
</svg>
)
}
2 changes: 2 additions & 0 deletions apps/docs/components/ui/icon-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
DiscordIcon,
DocumentIcon,
DropboxIcon,
DuckDuckGoIcon,
DynamoDBIcon,
ElasticsearchIcon,
ElevenLabsIcon,
Expand Down Expand Up @@ -212,6 +213,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
elevenlabs: ElevenLabsIcon,
elasticsearch: ElasticsearchIcon,
dynamodb: DynamoDBIcon,
duckduckgo: DuckDuckGoIcon,
dropbox: DropboxIcon,
discord: DiscordIcon,
datadog: DatadogIcon,
Expand Down
68 changes: 68 additions & 0 deletions apps/docs/content/docs/en/tools/duckduckgo.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: DuckDuckGo
description: Search with DuckDuckGo
---

import { BlockInfoCard } from "@/components/ui/block-info-card"

<BlockInfoCard
type="duckduckgo"
color="#FFFFFF"
/>

{/* MANUAL-CONTENT-START:intro */}
[DuckDuckGo](https://duckduckgo.com/) is a privacy-focused web search engine that delivers instant answers, abstracts, related topics, and more — without tracking you or your searches. DuckDuckGo makes it easy to find information without any user profiling or targeted ads.

With DuckDuckGo in Sim, you can:

- **Search the web**: Instantly find answers, facts, and overviews for a given search query
- **Get direct answers**: Retrieve specific responses for calculations, conversions, or factual queries
- **Access abstracts**: Receive short summaries or descriptions for your search topics
- **Fetch related topics**: Discover links and references relevant to your search
- **Filter output**: Optionally remove HTML or skip disambiguation for cleaner results

These features enable your Sim agents to automate access to fresh web knowledge — from surfacing facts in a workflow, to enriching documents and analysis with up-to-date information. Because DuckDuckGo’s Instant Answers API is open and does not require an API key, it’s simple and privacy-safe to integrate into your automated business processes.
{/* MANUAL-CONTENT-END */}


## Usage Instructions

Search the web using DuckDuckGo Instant Answers API. Returns instant answers, abstracts, related topics, and more. Free to use without an API key.



## Tools

### `duckduckgo_search`

Search the web using DuckDuckGo Instant Answers API. Returns instant answers, abstracts, and related topics for your query. Free to use without an API key.

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `query` | string | Yes | The search query to execute |
| `noHtml` | boolean | No | Remove HTML from text in results \(default: true\) |
| `skipDisambig` | boolean | No | Skip disambiguation results \(default: false\) |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `heading` | string | The heading/title of the instant answer |
| `abstract` | string | A short abstract summary of the topic |
| `abstractText` | string | Plain text version of the abstract |
| `abstractSource` | string | The source of the abstract \(e.g., Wikipedia\) |
| `abstractURL` | string | URL to the source of the abstract |
| `image` | string | URL to an image related to the topic |
| `answer` | string | Direct answer if available \(e.g., for calculations\) |
| `answerType` | string | Type of the answer \(e.g., calc, ip, etc.\) |
| `type` | string | Response type: A \(article\), D \(disambiguation\), C \(category\), N \(name\), E \(exclusive\) |
| `relatedTopics` | array | Array of related topics with URLs and descriptions |



## Notes

- Category: `tools`
- Type: `duckduckgo`
1 change: 1 addition & 0 deletions apps/docs/content/docs/en/tools/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"datadog",
"discord",
"dropbox",
"duckduckgo",
"dynamodb",
"elasticsearch",
"elevenlabs",
Expand Down
59 changes: 59 additions & 0 deletions apps/sim/blocks/blocks/duckduckgo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { DuckDuckGoIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import type { DuckDuckGoResponse } from '@/tools/duckduckgo/types'

export const DuckDuckGoBlock: BlockConfig<DuckDuckGoResponse> = {
type: 'duckduckgo',
name: 'DuckDuckGo',
description: 'Search with DuckDuckGo',
longDescription:
'Search the web using DuckDuckGo Instant Answers API. Returns instant answers, abstracts, related topics, and more. Free to use without an API key.',
docsLink: 'https://docs.sim.ai/tools/duckduckgo',
category: 'tools',
bgColor: '#FFFFFF',
icon: DuckDuckGoIcon,
subBlocks: [
{
id: 'query',
title: 'Search Query',
type: 'long-input',
placeholder: 'Enter your search query...',
required: true,
},
{
id: 'noHtml',
title: 'Remove HTML',
type: 'switch',
defaultValue: true,
},
{
id: 'skipDisambig',
title: 'Skip Disambiguation',
type: 'switch',
},
],
tools: {
access: ['duckduckgo_search'],
config: {
tool: () => 'duckduckgo_search',
},
},
inputs: {
query: { type: 'string', description: 'Search query terms' },
noHtml: { type: 'boolean', description: 'Remove HTML from text in results' },
skipDisambig: { type: 'boolean', description: 'Skip disambiguation results' },
},
outputs: {
heading: { type: 'string', description: 'The heading/title of the instant answer' },
abstract: { type: 'string', description: 'A short abstract summary of the topic' },
abstractText: { type: 'string', description: 'Plain text version of the abstract' },
abstractSource: { type: 'string', description: 'The source of the abstract' },
abstractURL: { type: 'string', description: 'URL to the source of the abstract' },
image: { type: 'string', description: 'URL to an image related to the topic' },
answer: { type: 'string', description: 'Direct answer if available' },
answerType: { type: 'string', description: 'Type of the answer' },
type: { type: 'string', description: 'Response type (A, D, C, N, E)' },
relatedTopics: { type: 'json', description: 'Array of related topics' },
results: { type: 'json', description: 'Array of external link results' },
},
}
2 changes: 2 additions & 0 deletions apps/sim/blocks/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { CursorBlock } from '@/blocks/blocks/cursor'
import { DatadogBlock } from '@/blocks/blocks/datadog'
import { DiscordBlock } from '@/blocks/blocks/discord'
import { DropboxBlock } from '@/blocks/blocks/dropbox'
import { DuckDuckGoBlock } from '@/blocks/blocks/duckduckgo'
import { DynamoDBBlock } from '@/blocks/blocks/dynamodb'
import { ElasticsearchBlock } from '@/blocks/blocks/elasticsearch'
import { ElevenLabsBlock } from '@/blocks/blocks/elevenlabs'
Expand Down Expand Up @@ -157,6 +158,7 @@ export const registry: Record<string, BlockConfig> = {
datadog: DatadogBlock,
discord: DiscordBlock,
dropbox: DropboxBlock,
duckduckgo: DuckDuckGoBlock,
elevenlabs: ElevenLabsBlock,
elasticsearch: ElasticsearchBlock,
evaluator: EvaluatorBlock,
Expand Down
24 changes: 24 additions & 0 deletions apps/sim/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4129,3 +4129,27 @@ export function CursorIcon(props: SVGProps<SVGSVGElement>) {
</svg>
)
}

export function DuckDuckGoIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='-108 -108 216 216'>
<circle r='108' fill='#d53' />
<circle r='96' fill='none' stroke='#ffffff' stroke-width='7' />
<path
d='M-32-55C-62-48-51-6-51-6l19 93 7 3M-39-73h-8l11 4s-11 0-11 7c24-1 35 5 35 5'
fill='#ddd'
/>
<path d='M25 95S1 57 1 32c0-47 31-7 31-44S1-58 1-58c-15-19-44-15-44-15l7 4s-7 2-9 4 19-3 28 5c-37 3-31 33-31 33l21 120' />
<path d='M25-1l38-10c34 5-29 24-33 23C0 7 9 32 45 24s9 20-24 9C-26 20-1-3 25-1' fill='#fc0' />
<path
d='M15 78l2-3c22 8 23 11 22-9s0-20-23-3c0-5-13-3-15 0-21-9-23-12-22 2 2 29 1 24 21 14'
fill='#6b5'
/>
<path d='M-1 67v12c1 2 17 2 17-2s-8 3-13 1-2-13-2-13' fill='#4a4' />
<path
d='M-23-32c-5-6-18-1-15 7 1-4 8-10 15-7m32 0c1-6 11-7 14-1-4-2-10-2-14 1m-33 16a2 2 0 1 1 0 1m-8 3a7 7 0 1 0 0-1m52-6a2 2 0 1 1 0 1m-6 3a6 6 0 1 0 0-1'
fill='#148'
/>
</svg>
)
}
3 changes: 3 additions & 0 deletions apps/sim/tools/duckduckgo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { searchTool } from '@/tools/duckduckgo/search'

export const duckduckgoSearchTool = searchTool
161 changes: 161 additions & 0 deletions apps/sim/tools/duckduckgo/search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import type { DuckDuckGoSearchParams, DuckDuckGoSearchResponse } from '@/tools/duckduckgo/types'
import type { ToolConfig } from '@/tools/types'

export const searchTool: ToolConfig<DuckDuckGoSearchParams, DuckDuckGoSearchResponse> = {
id: 'duckduckgo_search',
name: 'DuckDuckGo Search',
description:
'Search the web using DuckDuckGo Instant Answers API. Returns instant answers, abstracts, and related topics for your query. Free to use without an API key.',
version: '1.0.0',

params: {
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The search query to execute',
},
noHtml: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Remove HTML from text in results (default: true)',
},
skipDisambig: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Skip disambiguation results (default: false)',
},
},

request: {
url: (params) => {
const baseUrl = 'https://api.duckduckgo.com/'
const searchParams = new URLSearchParams({
q: params.query,
format: 'json',
no_html: params.noHtml !== false ? '1' : '0',
skip_disambig: params.skipDisambig ? '1' : '0',
})
return `${baseUrl}?${searchParams.toString()}`
},
method: 'GET',
headers: () => ({
Accept: 'application/json',
}),
},

transformResponse: async (response: Response) => {
const data = await response.json()

// Map related topics
const relatedTopics = (data.RelatedTopics || []).map((topic: any) => ({
FirstURL: topic.FirstURL,
Text: topic.Text,
Result: topic.Result,
Icon: topic.Icon
? {
URL: topic.Icon.URL,
Height: topic.Icon.Height,
Width: topic.Icon.Width,
}
: undefined,
}))

// Map results (external links)
const results = (data.Results || []).map((result: any) => ({
FirstURL: result.FirstURL,
Text: result.Text,
Result: result.Result,
Icon: result.Icon
? {
URL: result.Icon.URL,
Height: result.Icon.Height,
Width: result.Icon.Width,
}
: undefined,
}))

return {
success: true,
output: {
heading: data.Heading || '',
abstract: data.Abstract || '',
abstractText: data.AbstractText || '',
abstractSource: data.AbstractSource || '',
abstractURL: data.AbstractURL || '',
image: data.Image || '',
answer: data.Answer || '',
answerType: data.AnswerType || '',
type: data.Type || '',
relatedTopics,
results,
},
}
},

outputs: {
heading: {
type: 'string',
description: 'The heading/title of the instant answer',
},
abstract: {
type: 'string',
description: 'A short abstract summary of the topic',
},
abstractText: {
type: 'string',
description: 'Plain text version of the abstract',
},
abstractSource: {
type: 'string',
description: 'The source of the abstract (e.g., Wikipedia)',
},
abstractURL: {
type: 'string',
description: 'URL to the source of the abstract',
},
image: {
type: 'string',
description: 'URL to an image related to the topic',
},
answer: {
type: 'string',
description: 'Direct answer if available (e.g., for calculations)',
},
answerType: {
type: 'string',
description: 'Type of the answer (e.g., calc, ip, etc.)',
},
type: {
type: 'string',
description:
'Response type: A (article), D (disambiguation), C (category), N (name), E (exclusive)',
},
relatedTopics: {
type: 'array',
description: 'Array of related topics with URLs and descriptions',
items: {
type: 'object',
properties: {
FirstURL: { type: 'string', description: 'URL to the related topic' },
Text: { type: 'string', description: 'Description of the related topic' },
Result: { type: 'string', description: 'HTML result snippet' },
},
},
},
results: {
type: 'array',
description: 'Array of external link results',
items: {
type: 'object',
properties: {
FirstURL: { type: 'string', description: 'URL of the result' },
Text: { type: 'string', description: 'Description of the result' },
Result: { type: 'string', description: 'HTML result snippet' },
},
},
},
},
}
Loading