Skip to content
Open
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
27 changes: 26 additions & 1 deletion apps/docs/content/docs/integrations/linkup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ To implement Linkup in your agent, simply add the tool to your agent's configura

## Usage Instructions

Integrate Linkup into the workflow. Can search the web.
Integrate Linkup into the workflow. Can search the web and fetch the contents of a webpage as markdown.



Expand Down Expand Up @@ -59,4 +59,29 @@ Search the web for information using Linkup
| `answer` | string | The sourced answer to the search query |
| `sources` | array | Array of sources used to compile the answer, each containing name, url, and snippet |

### Linkup Fetch

Fetch a single webpage using Linkup and return its content as clean markdown, with optional raw HTML and extracted images.

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `url` | string | Yes | The URL of the webpage to fetch \(e.g., "https://docs.linkup.so") |
| `apiKey` | string | Yes | Enter your Linkup API key |
| `renderJs` | boolean | No | Render the JavaScript of the webpage before extracting its content |
| `includeRawHtml` | boolean | No | Include the raw HTML of the webpage in the response |
| `extractImages` | boolean | No | Extract the images from the webpage |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `markdown` | string | The clean markdown content of the webpage |
| `rawHtml` | string | The raw HTML of the webpage, when includeRawHtml is enabled |
| `images` | array | Images extracted from the webpage, when extractImages is enabled |
| ↳ `alt` | string | The alt text of the image |
| ↳ `url` | string | The URL of the image |
| `favicon` | string | The URL of the website favicon |


2 changes: 2 additions & 0 deletions apps/docs/content/docs/platform/costs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ When workflows use tool blocks with Sim's hosted API keys, costs are charged per
|-----------|------|
| Standard search | ~$0.006 |
| Deep search | ~$0.055 |
| Fetch | $0.001 |
| Fetch (with JavaScript rendering) | $0.005 |
</Tab>

<Tab>
Expand Down
110 changes: 104 additions & 6 deletions apps/sim/blocks/blocks/linkup.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { LinkupIcon } from '@/components/icons'
import { AuthMode, type BlockConfig, type BlockMeta, IntegrationType } from '@/blocks/types'
import type { LinkupSearchToolResponse } from '@/tools/linkup/types'
import type { LinkupResponse } from '@/tools/linkup/types'

export const LinkupBlock: BlockConfig<LinkupSearchToolResponse> = {
/**
* Blocks saved before the operation dropdown existed have no stored
* `operation`, so search fields are gated on "not fetch" rather than on
* `linkup_search` to keep those blocks rendering and serializing as before.
*/
const SEARCH_CONDITION = { field: 'operation', value: 'linkup_fetch', not: true }
const FETCH_CONDITION = { field: 'operation', value: 'linkup_fetch' }

export const LinkupBlock: BlockConfig<LinkupResponse> = {
type: 'linkup',
name: 'Linkup',
description: 'Search the web with Linkup',
authMode: AuthMode.ApiKey,
longDescription: 'Integrate Linkup into the workflow. Can search the web.',
longDescription:
'Integrate Linkup into the workflow. Can search the web and fetch the contents of a webpage as markdown.',
docsLink: 'https://docs.sim.ai/integrations/linkup',
category: 'tools',
integrationType: IntegrationType.Search,
Expand All @@ -16,20 +25,42 @@ export const LinkupBlock: BlockConfig<LinkupSearchToolResponse> = {
canvasPresentation: {
defaultTitle: 'Linkup',
sentences: {
/** Painted for blocks saved before the operation dropdown existed. */
default: [
{ text: 'Search the web for', field: 'q', core: true },
'Search the web',
{ text: 'for', field: 'q' },
Comment on lines +30 to +31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Legacy cards lose query placeholder

Saved blocks without an operation use this default sentence. When their query is empty, the new non-core clause disappears, leaving only “Search the web” where the card previously showed a Search Query placeholder. Keeping the query clause core would preserve that cue on existing cards.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

{ text: ', within', field: 'includeDomains' },
{ text: ', since', field: 'fromDate' },
],
byOperation: {
linkup_search: [
{ text: 'Search the web for', field: 'q', core: true },
{ text: ', within', field: 'includeDomains' },
{ text: ', since', field: 'fromDate' },
],
linkup_fetch: [{ text: 'Fetch', field: 'url', after: 'as markdown', core: true }],
},
},
},

subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'Search', id: 'linkup_search' },
{ label: 'Fetch', id: 'linkup_fetch' },
],
value: () => 'linkup_search',
},
// Search operation inputs
{
id: 'q',
title: 'Search Query',
type: 'long-input',
placeholder: 'Enter your search query',
condition: SEARCH_CONDITION,
required: true,
},
{
Expand All @@ -41,6 +72,7 @@ export const LinkupBlock: BlockConfig<LinkupSearchToolResponse> = {
{ label: 'Search', id: 'searchResults' },
],
value: () => 'sourcedAnswer',
condition: SEARCH_CONDITION,
},
{
id: 'depth',
Expand All @@ -51,30 +83,35 @@ export const LinkupBlock: BlockConfig<LinkupSearchToolResponse> = {
{ label: 'Deep', id: 'deep' },
],
value: () => 'standard',
condition: SEARCH_CONDITION,
},
{
id: 'includeImages',
title: 'Include Images',
type: 'switch',
condition: SEARCH_CONDITION,
mode: 'advanced',
},
{
id: 'includeInlineCitations',
title: 'Include Inline Citations',
type: 'switch',
condition: SEARCH_CONDITION,
mode: 'advanced',
},
{
id: 'includeSources',
title: 'Include Sources',
type: 'switch',
condition: SEARCH_CONDITION,
mode: 'advanced',
},
{
id: 'fromDate',
title: 'From Date',
type: 'short-input',
placeholder: 'YYYY-MM-DD',
condition: SEARCH_CONDITION,
mode: 'advanced',
wandConfig: {
enabled: true,
Expand All @@ -95,6 +132,7 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
title: 'To Date',
type: 'short-input',
placeholder: 'YYYY-MM-DD',
condition: SEARCH_CONDITION,
mode: 'advanced',
wandConfig: {
enabled: true,
Expand All @@ -115,13 +153,44 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
title: 'Include Domains',
type: 'long-input',
placeholder: 'example.com, another.com (comma-separated)',
condition: SEARCH_CONDITION,
mode: 'advanced',
},
{
id: 'excludeDomains',
title: 'Exclude Domains',
type: 'long-input',
placeholder: 'example.com, another.com (comma-separated)',
condition: SEARCH_CONDITION,
mode: 'advanced',
},
// Fetch operation inputs
{
id: 'url',
title: 'URL',
type: 'short-input',
placeholder: 'https://example.com',
condition: FETCH_CONDITION,
required: true,
},
{
id: 'renderJs',
title: 'Render JavaScript',
type: 'switch',
condition: FETCH_CONDITION,
},
{
id: 'includeRawHtml',
title: 'Include Raw HTML',
type: 'switch',
condition: FETCH_CONDITION,
mode: 'advanced',
},
{
id: 'extractImages',
title: 'Extract Images',
type: 'switch',
condition: FETCH_CONDITION,
mode: 'advanced',
},
{
Expand All @@ -136,12 +205,24 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
],

tools: {
access: ['linkup_search'],
access: ['linkup_search', 'linkup_fetch'],
config: {
tool: (params) => {
switch (params.operation) {
case 'linkup_fetch':
return 'linkup_fetch'
default:
return 'linkup_search'
}
},
},
},

inputs: {
q: { type: 'string', description: 'Search query' },
operation: { type: 'string', description: 'Operation to perform' },
apiKey: { type: 'string', description: 'Linkup API key' },
// Search operation
q: { type: 'string', description: 'Search query' },
depth: { type: 'string', description: 'Search depth level' },
outputType: { type: 'string', description: 'Output format type' },
includeImages: { type: 'boolean', description: 'Include images in results' },
Expand All @@ -157,11 +238,22 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
type: 'string',
description: 'Domains to exclude from search (comma-separated)',
},
// Fetch operation
url: { type: 'string', description: 'URL of the webpage to fetch' },
renderJs: { type: 'boolean', description: 'Render JavaScript before extracting content' },
includeRawHtml: { type: 'boolean', description: 'Include the raw HTML in the response' },
extractImages: { type: 'boolean', description: 'Extract images from the webpage' },
},

outputs: {
// Search output
answer: { type: 'string', description: 'Generated answer' },
sources: { type: 'json', description: 'Source references' },
// Fetch output
markdown: { type: 'string', description: 'Webpage content as markdown' },
rawHtml: { type: 'string', description: 'Raw HTML of the webpage, when requested' },
images: { type: 'json', description: '[{alt, url}] — images extracted from the webpage' },
favicon: { type: 'string', description: 'URL of the website favicon' },
},
}

Expand Down Expand Up @@ -258,5 +350,11 @@ export const LinkupBlockMeta = {
content:
'# Monitor Topic Mentions\n\nTrack fresh mentions of a topic or competitor.\n\n## Steps\n1. Set the search query to the brand, competitor, or topic to monitor.\n2. Use the Search output type and set the from date to the start of the window you want to cover.\n3. Optionally restrict to news or specific domains.\n4. Filter the results to genuinely new or relevant mentions and summarize each.\n\n## Output\nA list of new mentions with source URL, date, and a one-line summary of each.',
},
{
name: 'fetch-page-markdown',
description: 'Use Linkup Fetch to turn a webpage into clean markdown for downstream steps.',
content:
'# Fetch Page Markdown\n\nRead the contents of a specific webpage with Linkup.\n\n## Steps\n1. Use the Fetch operation with the full URL of the page.\n2. Enable Render JavaScript for single-page apps or pages that load their content client-side.\n3. Enable Extract Images when the page images matter, and Include Raw HTML only when a later step needs the original markup.\n4. Pass the markdown to a summarizer, extractor, or knowledge base.\n\n## Output\nThe page content as markdown, plus any extracted images and the raw HTML when requested.',
},
],
} as const satisfies BlockMeta
2 changes: 1 addition & 1 deletion apps/sim/tools/generated/tool-ids.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/sim/tools/generated/tool-metadata.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/sim/tools/generated/tool-outputs.ts

Large diffs are not rendered by default.

Loading