Skip to content

Commit 155d7b5

Browse files
waleedlatif1claude
andauthored
feat(tinyfish): support Browser Context Profiles on agent runs (#7483)
* feat(tinyfish): support Browser Context Profiles on agent runs Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ej1gsFPVzN5xZZ3QzvK8bD * fix(tinyfish): keep profile activation user-controlled and switch-safe Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ej1gsFPVzN5xZZ3QzvK8bD * chore(tinyfish): name the real producer of a serialized switch value Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ej1gsFPVzN5xZZ3QzvK8bD * fix(tinyfish): declare the nullable profile metadata fields nullable Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ej1gsFPVzN5xZZ3QzvK8bD --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent fa4c499 commit 155d7b5

12 files changed

Lines changed: 459 additions & 20 deletions

File tree

apps/docs/content/docs/integrations/tinyfish.mdx

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ With TinyFish in Sim, you can:
2323

2424
- **Automate any site, API or not**: Log into vendor portals, legacy ERPs, and internal tools that never shipped an API, and pull the data out.
2525
- **Get typed results, not scraped HTML**: Supply a JSON Schema in **Output Schema** and TinyFish holds the agent to it, re-prompting on mismatch and reporting every field that did not match in `schemaValidation`.
26-
- **Survive bot detection**: Switch **Browser Profile** to `stealth` for anti-detection, and enable the Tetra proxy with a country when the page is geo-restricted.
26+
- **Survive bot detection**: Switch **Browser Engine** to `stealth` for anti-detection, and enable the Tetra proxy with a country when the page is geo-restricted.
27+
- **Stay logged in between runs**: Enable **Use Browser Profile** to start a run from a Browser Context Profile — saved browser state you log into once on TinyFish. **List Browser Profiles** returns the ids to choose from; leaving the id empty uses your default profile. Pair it with the vault so an expired session can be repaired.
2728
- **Log in safely**: Connect a password manager to TinyFish's vault, then enable **Use Vault Credentials** and scope a run to specific credential URIs. **List Vault Items** returns those URIs as display-safe metadata — labels, domains, field names — so credentials never travel through the workflow.
2829
- **Run work that outlives a step**: **Start Agent Run** queues an automation and returns a run ID immediately; **Get Run**, **Cancel Run**, and **List Runs** track it afterwards, and a webhook URL can notify you on completion.
2930
- **Read the live web cheaply**: Pair **Search** and **Fetch URLs** to gather current sources before an agent writes or answers.
@@ -74,14 +75,16 @@ Run a TinyFish web agent against a website and wait for it to finish, returning
7475
| --------- | ---- | -------- | ----------- |
7576
| `url` | string | Yes | Target website URL the agent starts on |
7677
| `goal` | string | Yes | Natural-language description of what to accomplish on the website |
77-
| `browserProfile` | string | No | Browser engine: "lite" \(standard\) or "stealth" \(anti-detection\) |
78+
| `browserProfile` | string | No | Browser engine: "lite" \(standard\) or "stealth" \(anti-detection\). Not a Browser Context Profile — use useProfile for saved logins |
7879
| `agentMode` | string | No | Agent behavior: "default" or "strict" \(fail fast\) |
7980
| `maxSteps` | number | No | Maximum tool-call steps before the agent stops \(1-500, default 150\) |
8081
| `outputSchema` | json | No | JSON Schema draft-07 contract the run result must satisfy |
8182
| `proxyEnabled` | boolean | No | Route the run through TinyFish’s Tetra proxy |
8283
| `proxyCountryCode` | string | No | Proxy country: US, GB, CA, DE, FR, JP, or AU |
8384
| `useVault` | boolean | No | Let the run use credentials from the connected TinyFish vault |
8485
| `credentialItemIds` | string | No | Comma-separated vault credential URIs to scope the run to |
86+
| `useProfile` | boolean | No | Start the run from a saved Browser Context Profile, reusing the logged-in session stored in it |
87+
| `profileId` | string | No | Browser Context Profile to start from, such as "prof_abc123". Requires useProfile; omit to use the account default |
8588
| `apiKey` | string | Yes | TinyFish API key |
8689

8790
#### Output
@@ -120,14 +123,16 @@ Queue a TinyFish web agent run and return its run ID immediately, without waitin
120123
| --------- | ---- | -------- | ----------- |
121124
| `url` | string | Yes | Target website URL the agent starts on |
122125
| `goal` | string | Yes | Natural-language description of what to accomplish on the website |
123-
| `browserProfile` | string | No | Browser engine: "lite" \(standard\) or "stealth" \(anti-detection\) |
126+
| `browserProfile` | string | No | Browser engine: "lite" \(standard\) or "stealth" \(anti-detection\). Not a Browser Context Profile — use useProfile for saved logins |
124127
| `agentMode` | string | No | Agent behavior: "default" or "strict" \(fail fast\) |
125128
| `maxSteps` | number | No | Maximum tool-call steps before the agent stops \(1-500, default 150\) |
126129
| `outputSchema` | json | No | JSON Schema draft-07 contract the run result must satisfy |
127130
| `proxyEnabled` | boolean | No | Route the run through TinyFish’s Tetra proxy |
128131
| `proxyCountryCode` | string | No | Proxy country: US, GB, CA, DE, FR, JP, or AU |
129132
| `useVault` | boolean | No | Let the run use credentials from the connected TinyFish vault |
130133
| `credentialItemIds` | string | No | Comma-separated vault credential URIs to scope the run to |
134+
| `useProfile` | boolean | No | Start the run from a saved Browser Context Profile, reusing the logged-in session stored in it |
135+
| `profileId` | string | No | Browser Context Profile to start from, such as "prof_abc123". Requires useProfile; omit to use the account default |
131136
| `apiKey` | string | Yes | TinyFish API key |
132137
| `webhookUrl` | string | No | HTTPS URL notified when the run completes, fails, or is cancelled |
133138

@@ -347,4 +352,26 @@ List the credentials available from password managers connected to TinyFish, wit
347352
|`type` | string | STRING, CONCEALED, or OTP |
348353
|`hasTotp` | boolean | Whether the credential carries a TOTP secret |
349354

355+
### TinyFish List Browser Profiles
356+
357+
List the Browser Context Profiles saved on the TinyFish account, with the ids an agent run can start from to reuse a logged-in session
358+
359+
#### Input
360+
361+
| Parameter | Type | Required | Description |
362+
| --------- | ---- | -------- | ----------- |
363+
| `apiKey` | string | Yes | TinyFish API key |
364+
365+
#### Output
366+
367+
| Parameter | Type | Description |
368+
| --------- | ---- | ----------- |
369+
| `profiles` | array | Browser Context Profiles an agent run can start from |
370+
|`profileId` | string | Profile identifier, used as the Browser Profile ID on a run |
371+
|`name` | string | Profile name, such as "Salesforce Production" |
372+
|`proxyCountryCode` | string | Country the profile proxies through, null when it has no proxy |
373+
|`fingerprintSeed` | string | Seed for the browser fingerprint the profile replays, null when the API omits it |
374+
|`createdAt` | string | ISO 8601 timestamp when the profile was created, null when the API omits it |
375+
|`isDefault` | boolean | Whether runs with no Browser Profile ID use this one, null when the API does not report it |
376+
350377

apps/sim/blocks/blocks/tinyfish.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export const TinyFishBlock: BlockConfig<TinyFishRunResponse> = {
6565
{ text: 'as', field: 'format' },
6666
],
6767
tinyfish_list_vault_items: ['List credentials from the connected vault'],
68+
tinyfish_list_profiles: ['List saved browser profiles'],
6869
},
6970
},
7071
},
@@ -82,6 +83,7 @@ export const TinyFishBlock: BlockConfig<TinyFishRunResponse> = {
8283
{ label: 'Search', id: 'tinyfish_search' },
8384
{ label: 'Fetch URLs', id: 'tinyfish_fetch' },
8485
{ label: 'List Vault Items', id: 'tinyfish_list_vault_items' },
86+
{ label: 'List Browser Profiles', id: 'tinyfish_list_profiles' },
8587
],
8688
value: () => 'tinyfish_run',
8789
},
@@ -147,8 +149,9 @@ Return ONLY the JSON Schema - no explanations, no extra text.`,
147149
},
148150
{
149151
id: 'browserProfile',
150-
title: 'Browser Profile',
152+
title: 'Browser Engine',
151153
type: 'dropdown',
154+
description: 'Which browser the agent drives. Unrelated to a saved Browser Context Profile',
152155
options: [
153156
{ label: 'Lite (standard browser)', id: 'lite' },
154157
{ label: 'Stealth (anti-detection)', id: 'stealth' },
@@ -220,6 +223,28 @@ Return ONLY the JSON Schema - no explanations, no extra text.`,
220223
},
221224
mode: 'advanced',
222225
},
226+
{
227+
id: 'useProfile',
228+
title: 'Use Browser Profile',
229+
type: 'switch',
230+
description: 'Start the run from a saved browser session, so the agent is already logged in',
231+
condition: { field: 'operation', value: AUTOMATION_OPERATIONS },
232+
mode: 'advanced',
233+
},
234+
{
235+
id: 'profileId',
236+
title: 'Browser Profile ID',
237+
type: 'short-input',
238+
placeholder: 'prof_abc123def4567890',
239+
description:
240+
'Run List Browser Profiles to find it. Leave empty to use your default profile, which the run requires you to have set',
241+
condition: {
242+
field: 'operation',
243+
value: AUTOMATION_OPERATIONS,
244+
and: { field: 'useProfile', value: true },
245+
},
246+
mode: 'advanced',
247+
},
223248
{
224249
id: 'webhookUrl',
225250
title: 'Webhook URL',
@@ -439,6 +464,7 @@ Return ONLY the comma-separated URL list - no explanations, no extra text.`,
439464
'tinyfish_search',
440465
'tinyfish_fetch',
441466
'tinyfish_list_vault_items',
467+
'tinyfish_list_profiles',
442468
],
443469
config: {
444470
tool: (params) => {
@@ -457,6 +483,8 @@ Return ONLY the comma-separated URL list - no explanations, no extra text.`,
457483
return 'tinyfish_fetch'
458484
case 'tinyfish_list_vault_items':
459485
return 'tinyfish_list_vault_items'
486+
case 'tinyfish_list_profiles':
487+
return 'tinyfish_list_profiles'
460488
default:
461489
return 'tinyfish_run'
462490
}
@@ -496,6 +524,8 @@ Return ONLY the comma-separated URL list - no explanations, no extra text.`,
496524
proxyCountryCode: { type: 'string', description: 'Proxy country code' },
497525
useVault: { type: 'boolean', description: 'Allow vault credentials during the run' },
498526
credentialItemIds: { type: 'string', description: 'Comma-separated vault credential URIs' },
527+
useProfile: { type: 'boolean', description: 'Start the run from a saved browser session' },
528+
profileId: { type: 'string', description: 'Browser Context Profile to start the run from' },
499529
webhookUrl: { type: 'string', description: 'HTTPS endpoint notified on run lifecycle events' },
500530
runId: { type: 'string', description: 'Run identifier' },
501531
status: { type: 'string', description: 'Run status filter' },
@@ -566,6 +596,11 @@ Return ONLY the comma-separated URL list - no explanations, no extra text.`,
566596
description:
567597
'Vault credentials available to a run [{itemId, connectionId, label, vaultName, domains, fieldMetadata, hasTotp}]',
568598
},
599+
profiles: {
600+
type: 'json',
601+
description:
602+
'Browser Context Profiles a run can start from [{profileId, name, proxyCountryCode, fingerprintSeed, createdAt, isDefault}]. Every field but profileId and name can be null when the API omits it',
603+
},
569604
},
570605
}
571606

@@ -655,14 +690,14 @@ export const TinyFishBlockMeta = {
655690
description:
656691
'Drive a TinyFish web agent to navigate a site and return data matching a JSON schema. Use to pull records — prices, listings, table rows — from pages that have no API.',
657692
content:
658-
'# Extract Structured Data From Site\n\nUse the TinyFish Run Agent operation to read a website and return structured data.\n\n## Steps\n1. Set Website URL to the page the agent should start on. Starting closer to the data costs fewer steps.\n2. Write a Goal that names exactly what to collect and where, e.g. "open the pricing page and collect every plan name and monthly price".\n3. Provide an Output Schema (JSON Schema draft-07) describing the fields you want back. TinyFish re-prompts the agent when the result does not match and reports the mismatches in `schemaValidation`.\n4. Raise Max Steps for deeper flows; switch Browser Profile to Stealth when the site blocks automation.\n\n## Output\nReturn the extracted `result` object. Check `schemaValidation.valid` before trusting it, and report any field the agent could not find rather than filling it in.',
693+
'# Extract Structured Data From Site\n\nUse the TinyFish Run Agent operation to read a website and return structured data.\n\n## Steps\n1. Set Website URL to the page the agent should start on. Starting closer to the data costs fewer steps.\n2. Write a Goal that names exactly what to collect and where, e.g. "open the pricing page and collect every plan name and monthly price".\n3. Provide an Output Schema (JSON Schema draft-07) describing the fields you want back. TinyFish re-prompts the agent when the result does not match and reports the mismatches in `schemaValidation`.\n4. Raise Max Steps for deeper flows; switch Browser Engine to Stealth when the site blocks automation.\n\n## Output\nReturn the extracted `result` object. Check `schemaValidation.valid` before trusting it, and report any field the agent could not find rather than filling it in.',
659694
},
660695
{
661696
name: 'automate-web-task',
662697
description:
663698
'Have a TinyFish agent complete a multi-step task on a website — logging in, navigating, filling and submitting forms. Use when a site has no API and a person would normally do the clicks.',
664699
content:
665-
'# Automate Web Task\n\nUse the TinyFish Run Agent operation to complete a goal-oriented task on the web.\n\n## Steps\n1. Set Website URL to the entry point and write a Goal that states the steps and the success condition, e.g. "log in, open Billing, download the latest invoice".\n2. Turn on Use Vault Credentials when the task needs a login, and scope it with Vault Credential URIs so only the intended credential is available.\n3. Use Agent Mode "strict" when the run is a test that should fail fast instead of improvising.\n4. Enable Use Proxy and pick a Proxy Country when the site is geo-restricted.\n\n## Output\nReport whether the run completed, what the agent extracted, and the step count. On failure, quote the `error` message and category — AGENT_FAILURE means the goal needs rewording, SYSTEM_FAILURE is worth retrying.',
700+
'# Automate Web Task\n\nUse the TinyFish Run Agent operation to complete a goal-oriented task on the web.\n\n## Steps\n1. Set Website URL to the entry point and write a Goal that states the steps and the success condition, e.g. "log in, open Billing, download the latest invoice".\n2. Turn on Use Browser Profile to start from a session that is already logged in, and give a Browser Profile ID to pick one. Turn on Use Vault Credentials when the task needs to log in itself, and scope it with Vault Credential URIs so only the intended credential is available. Pairing both lets TinyFish repair a profile whose session has expired.\n3. Use Agent Mode "strict" when the run is a test that should fail fast instead of improvising.\n4. Enable Use Proxy and pick a Proxy Country when the site is geo-restricted.\n\n## Output\nReport whether the run completed, what the agent extracted, and the step count. On failure, quote the `error` message and category — AGENT_FAILURE means the goal needs rewording, SYSTEM_FAILURE is worth retrying.',
666701
},
667702
{
668703
name: 'search-and-read-the-web',

apps/sim/tools/generated/tool-ids.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/sim/tools/generated/tool-metadata.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/sim/tools/generated/tool-outputs.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/sim/tools/registry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5317,6 +5317,7 @@ import {
53175317
tinyfishCancelRunTool,
53185318
tinyfishFetchTool,
53195319
tinyfishGetRunTool,
5320+
tinyfishListProfilesTool,
53205321
tinyfishListRunsTool,
53215322
tinyfishListVaultItemsTool,
53225323
tinyfishRunAsyncTool,
@@ -9394,6 +9395,7 @@ export const tools: Record<string, ExecutableToolConfig> = {
93949395
tinyfish_search: tinyfishSearchTool,
93959396
tinyfish_fetch: tinyfishFetchTool,
93969397
tinyfish_list_vault_items: tinyfishListVaultItemsTool,
9398+
tinyfish_list_profiles: tinyfishListProfilesTool,
93979399
stagehand_extract: stagehandExtractTool,
93989400
stagehand_agent: stagehandAgentTool,
93999401
mem0_add_memories: mem0AddMemoriesTool,

apps/sim/tools/tinyfish/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { cancelRunTool } from '@/tools/tinyfish/cancel_run'
22
import { fetchUrlsTool } from '@/tools/tinyfish/fetch_urls'
33
import { getRunTool } from '@/tools/tinyfish/get_run'
4+
import { listProfilesTool } from '@/tools/tinyfish/list_profiles'
45
import { listRunsTool } from '@/tools/tinyfish/list_runs'
56
import { listVaultItemsTool } from '@/tools/tinyfish/list_vault_items'
67
import { runTool } from '@/tools/tinyfish/run'
@@ -10,6 +11,7 @@ import { searchTool } from '@/tools/tinyfish/search'
1011
export const tinyfishCancelRunTool = cancelRunTool
1112
export const tinyfishFetchTool = fetchUrlsTool
1213
export const tinyfishGetRunTool = getRunTool
14+
export const tinyfishListProfilesTool = listProfilesTool
1315
export const tinyfishListRunsTool = listRunsTool
1416
export const tinyfishListVaultItemsTool = listVaultItemsTool
1517
export const tinyfishRunTool = runTool
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import type {
2+
TinyFishListProfilesParams,
3+
TinyFishListProfilesResponse,
4+
TinyFishRawProfile,
5+
TinyFishRawProfiles,
6+
} from '@/tools/tinyfish/types'
7+
import {
8+
TINYFISH_AGENT_API_BASE,
9+
tinyfishErrorMessage,
10+
tinyfishHeaders,
11+
} from '@/tools/tinyfish/utils'
12+
import type { ToolConfig } from '@/tools/types'
13+
14+
/**
15+
* Reads the profile array out of the list payload.
16+
*
17+
* TinyFish publishes no example response for `GET /v1/profiles`, so all three
18+
* shapes a list endpoint plausibly returns are accepted rather than betting on
19+
* one: a bare array, and the `profiles` and `data` envelopes its other list
20+
* endpoints use.
21+
*/
22+
function extractProfiles(data: TinyFishRawProfiles | TinyFishRawProfile[]): TinyFishRawProfile[] {
23+
if (Array.isArray(data)) return data
24+
return data?.profiles ?? data?.data ?? []
25+
}
26+
27+
/**
28+
* Lists the Browser Context Profiles saved on the TinyFish account.
29+
*
30+
* A profile carries logged-in browser state, so this returns the ids a run
31+
* selects with `profileId` — never the cookies or storage behind them. Profiles
32+
* are created and logged into through TinyFish's own setup-session flow, which
33+
* hands a live CDP URL to a browser driver and cannot run inside a block.
34+
*/
35+
export const listProfilesTool: ToolConfig<
36+
TinyFishListProfilesParams,
37+
TinyFishListProfilesResponse
38+
> = {
39+
id: 'tinyfish_list_profiles',
40+
name: 'TinyFish List Browser Profiles',
41+
description:
42+
'List the Browser Context Profiles saved on the TinyFish account, with the ids an agent run can start from to reuse a logged-in session',
43+
version: '1.0.0',
44+
45+
params: {
46+
apiKey: {
47+
type: 'string',
48+
required: true,
49+
visibility: 'user-only',
50+
description: 'TinyFish API key',
51+
},
52+
},
53+
54+
request: {
55+
url: `${TINYFISH_AGENT_API_BASE}/v1/profiles`,
56+
method: 'GET',
57+
headers: (params) => tinyfishHeaders(params.apiKey),
58+
},
59+
60+
transformResponse: async (response: Response) => {
61+
if (!response.ok) {
62+
throw new Error(await tinyfishErrorMessage(response))
63+
}
64+
65+
const data = (await response.json()) as TinyFishRawProfiles | TinyFishRawProfile[]
66+
67+
return {
68+
success: true,
69+
output: {
70+
profiles: extractProfiles(data).map((profile) => ({
71+
profileId: profile?.id ?? '',
72+
name: profile?.name ?? '',
73+
proxyCountryCode: profile?.proxy_country_code ?? null,
74+
fingerprintSeed: profile?.fingerprint_seed ?? null,
75+
createdAt: profile?.created_at ?? null,
76+
isDefault: profile?.set_as_default ?? profile?.is_default ?? null,
77+
})),
78+
},
79+
}
80+
},
81+
82+
outputs: {
83+
profiles: {
84+
type: 'array',
85+
description: 'Browser Context Profiles an agent run can start from',
86+
items: {
87+
type: 'object',
88+
properties: {
89+
profileId: {
90+
type: 'string',
91+
description: 'Profile identifier, used as the Browser Profile ID on a run',
92+
},
93+
name: { type: 'string', description: 'Profile name, such as "Salesforce Production"' },
94+
proxyCountryCode: {
95+
type: 'string',
96+
description: 'Country the profile proxies through, null when it has no proxy',
97+
optional: true,
98+
nullable: true,
99+
},
100+
fingerprintSeed: {
101+
type: 'string',
102+
description:
103+
'Seed for the browser fingerprint the profile replays, null when the API omits it',
104+
optional: true,
105+
nullable: true,
106+
},
107+
createdAt: {
108+
type: 'string',
109+
description:
110+
'ISO 8601 timestamp when the profile was created, null when the API omits it',
111+
optional: true,
112+
nullable: true,
113+
},
114+
isDefault: {
115+
type: 'boolean',
116+
description:
117+
'Whether runs with no Browser Profile ID use this one, null when the API does not report it',
118+
optional: true,
119+
nullable: true,
120+
},
121+
},
122+
},
123+
},
124+
},
125+
}

0 commit comments

Comments
 (0)