@proveanything/smartlinks 1.17.0 → 1.17.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api/ai.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ContentPart, FunctionCall, ToolCall, ChatMessage, ToolDefinition, ResponseTool, ResponseInputItem, ResponsesRequest, ResponsesResult, ResponsesStreamEvent, ChatCompletionRequest, ChatCompletionChoice, ChatCompletionResponse, ChatCompletionChunk, AIModel, AIModelListParams, AIModelListResponse, DocumentChunk, IndexDocumentRequest, IndexDocumentResponse, ConfigureAssistantRequest, ConfigureAssistantResponse, PublicChatRequest, PublicChatResponse, Session, RateLimitStatus, SessionStatistics, VoiceSessionRequest, VoiceSessionResponse, EphemeralTokenRequest, EphemeralTokenResponse, TranscriptionResponse, TTSRequest, GeneratePodcastRequest, PodcastScript, GeneratePodcastResponse, PodcastStatus, AIGenerateContentRequest, AIGenerateImageRequest, AISearchPhotosRequest, AISearchPhotosPhoto } from "../types/ai";
1
+ import type { ContentPart, FunctionCall, ToolCall, ChatMessage, ToolDefinition, ResponseTool, ResponseInputItem, ResponsesRequest, ResponsesResult, ResponsesStreamEvent, ChatCompletionRequest, ChatCompletionChoice, ChatCompletionResponse, ChatCompletionChunk, AIModel, AIModelListParams, AIModelListResponse, AgentRunRequest, AgentRunResult, AgentToolsQuery, AgentToolsResponse, SkillsListResponse, CatalogResponse, DocumentChunk, IndexDocumentRequest, IndexDocumentResponse, ConfigureAssistantRequest, ConfigureAssistantResponse, PublicChatRequest, PublicChatResponse, Session, RateLimitStatus, SessionStatistics, VoiceSessionRequest, VoiceSessionResponse, EphemeralTokenRequest, EphemeralTokenResponse, TranscriptionResponse, TTSRequest, GeneratePodcastRequest, PodcastScript, GeneratePodcastResponse, PodcastStatus, AIGenerateContentRequest, AIGenerateImageRequest, AISearchPhotosRequest, AISearchPhotosPhoto } from "../types/ai";
2
2
  export type { ContentPart, FunctionCall, ToolCall, ChatMessage, ToolDefinition, ResponseTool, ResponseInputItem, ResponsesRequest, ResponsesResult, ResponsesStreamEvent, ChatCompletionRequest, ChatCompletionChoice, ChatCompletionResponse, ChatCompletionChunk, AIModel, AIModelListParams, AIModelListResponse, DocumentChunk, IndexDocumentRequest, IndexDocumentResponse, ConfigureAssistantRequest, ConfigureAssistantResponse, PublicChatRequest, PublicChatResponse, Session, RateLimitStatus, SessionStatistics, VoiceSessionRequest, VoiceSessionResponse, EphemeralTokenRequest, EphemeralTokenResponse, TranscriptionResponse, TTSRequest, GeneratePodcastRequest, PodcastScript, GeneratePodcastResponse, PodcastStatus, AIGenerateContentRequest, AIGenerateImageRequest, AISearchPhotosRequest, AISearchPhotosPhoto, };
3
3
  declare namespace aiInternal {
4
4
  namespace chat {
@@ -21,6 +21,30 @@ declare namespace aiInternal {
21
21
  function create(collectionId: string, request: ChatCompletionRequest): Promise<ChatCompletionResponse | AsyncIterable<ChatCompletionChunk>>;
22
22
  }
23
23
  }
24
+ namespace agent {
25
+ /**
26
+ * Run the server-side AI agent loop once: assembles the tool set, runs the
27
+ * model, executes tool calls, and returns the final text + the tool trace.
28
+ * POST /admin/collection/:collectionId/ai/agent/run
29
+ */
30
+ function run(collectionId: string, body: AgentRunRequest): Promise<AgentRunResult>;
31
+ /**
32
+ * List the tools the agent can use (optionally scoped by capability / name).
33
+ * GET /admin/collection/:collectionId/ai/agent/tools
34
+ */
35
+ function listTools(collectionId: string, query?: AgentToolsQuery): Promise<AgentToolsResponse>;
36
+ }
37
+ namespace skills {
38
+ /** List the skills apps can invoke (name, description, input/output schema). */
39
+ function list(collectionId: string): Promise<SkillsListResponse>;
40
+ /**
41
+ * Invoke a skill by name with structured input — the app-facing verb; no
42
+ * prompt-shaping. POST /admin/collection/:collectionId/ai/skills/:name/run
43
+ */
44
+ function run<T = any>(collectionId: string, name: string, input?: Record<string, any>): Promise<T>;
45
+ }
46
+ /** The full self-describing catalog (tools + skills). GET /ai/catalog */
47
+ function catalog(collectionId: string): Promise<CatalogResponse>;
24
48
  namespace models {
25
49
  /**
26
50
  * List available AI models
@@ -181,6 +205,15 @@ export declare const ai: {
181
205
  listen: typeof aiInternal.voice.listen;
182
206
  speak: typeof aiInternal.voice.speak;
183
207
  };
208
+ agent: {
209
+ run: typeof aiInternal.agent.run;
210
+ listTools: typeof aiInternal.agent.listTools;
211
+ };
212
+ skills: {
213
+ list: typeof aiInternal.skills.list;
214
+ run: typeof aiInternal.skills.run;
215
+ };
216
+ catalog: typeof aiInternal.catalog;
184
217
  generateContent: typeof aiInternal.generateContent;
185
218
  generateImage: typeof aiInternal.generateImage;
186
219
  searchPhotos: typeof aiInternal.searchPhotos;
package/dist/api/ai.js CHANGED
@@ -59,6 +59,61 @@ var aiInternal;
59
59
  })(completions = chat.completions || (chat.completions = {}));
60
60
  })(chat = aiInternal.chat || (aiInternal.chat = {}));
61
61
  // ============================================================================
62
+ // Agent API (server-side tool-registry loop)
63
+ // ============================================================================
64
+ let agent;
65
+ (function (agent) {
66
+ /**
67
+ * Run the server-side AI agent loop once: assembles the tool set, runs the
68
+ * model, executes tool calls, and returns the final text + the tool trace.
69
+ * POST /admin/collection/:collectionId/ai/agent/run
70
+ */
71
+ async function run(collectionId, body) {
72
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/ai/agent/run`;
73
+ return post(path, body);
74
+ }
75
+ agent.run = run;
76
+ /**
77
+ * List the tools the agent can use (optionally scoped by capability / name).
78
+ * GET /admin/collection/:collectionId/ai/agent/tools
79
+ */
80
+ async function listTools(collectionId, query = {}) {
81
+ const search = new URLSearchParams();
82
+ for (const [k, v] of Object.entries(query)) {
83
+ if (v)
84
+ search.set(k, String(v));
85
+ }
86
+ const qs = search.toString();
87
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/ai/agent/tools${qs ? `?${qs}` : ''}`;
88
+ return request(path);
89
+ }
90
+ agent.listTools = listTools;
91
+ })(agent = aiInternal.agent || (aiInternal.agent = {}));
92
+ // ============================================================================
93
+ // Skills + Catalog (app-facing discovery)
94
+ // ============================================================================
95
+ let skills;
96
+ (function (skills) {
97
+ /** List the skills apps can invoke (name, description, input/output schema). */
98
+ async function list(collectionId) {
99
+ return request(`/admin/collection/${encodeURIComponent(collectionId)}/ai/skills`);
100
+ }
101
+ skills.list = list;
102
+ /**
103
+ * Invoke a skill by name with structured input — the app-facing verb; no
104
+ * prompt-shaping. POST /admin/collection/:collectionId/ai/skills/:name/run
105
+ */
106
+ async function run(collectionId, name, input = {}) {
107
+ return post(`/admin/collection/${encodeURIComponent(collectionId)}/ai/skills/${encodeURIComponent(name)}/run`, input);
108
+ }
109
+ skills.run = run;
110
+ })(skills = aiInternal.skills || (aiInternal.skills = {}));
111
+ /** The full self-describing catalog (tools + skills). GET /ai/catalog */
112
+ async function catalog(collectionId) {
113
+ return request(`/admin/collection/${encodeURIComponent(collectionId)}/ai/catalog`);
114
+ }
115
+ aiInternal.catalog = catalog;
116
+ // ============================================================================
62
117
  // Models API
63
118
  // ============================================================================
64
119
  let models;
@@ -377,6 +432,15 @@ export const ai = {
377
432
  listen: aiInternal.voice.listen,
378
433
  speak: aiInternal.voice.speak,
379
434
  },
435
+ agent: {
436
+ run: aiInternal.agent.run,
437
+ listTools: aiInternal.agent.listTools,
438
+ },
439
+ skills: {
440
+ list: aiInternal.skills.list,
441
+ run: aiInternal.skills.run,
442
+ },
443
+ catalog: aiInternal.catalog,
380
444
  generateContent: aiInternal.generateContent,
381
445
  generateImage: aiInternal.generateImage,
382
446
  searchPhotos: aiInternal.searchPhotos,
@@ -39,6 +39,7 @@ export { loyalty } from "./loyalty";
39
39
  export { translations } from "./translations";
40
40
  export { integrations } from "./integrations";
41
41
  export { secrets } from "./secrets";
42
+ export { research } from "./research";
42
43
  export { config } from "./config";
43
44
  export { http } from "./http";
44
45
  export { navigation } from "./navigation";
package/dist/api/index.js CHANGED
@@ -42,6 +42,7 @@ export { loyalty } from "./loyalty";
42
42
  export { translations } from "./translations";
43
43
  export { integrations } from "./integrations";
44
44
  export { secrets } from "./secrets";
45
+ export { research } from "./research";
45
46
  export { config } from "./config";
46
47
  export { http } from "./http";
47
48
  export { navigation } from "./navigation";
@@ -0,0 +1,9 @@
1
+ import type { ResearchFetchRequest, ResearchFetchResult } from "../types/research";
2
+ export declare namespace research {
3
+ /**
4
+ * Fetch + extract a web page: clean markdown, page metadata, and any schema.org
5
+ * JSON-LD (filtered by `type` when given). Firecrawl-primary, cached per collection.
6
+ * POST /admin/collection/:collectionId/research/fetch
7
+ */
8
+ function fetch(collectionId: string, body: ResearchFetchRequest): Promise<ResearchFetchResult>;
9
+ }
@@ -0,0 +1,21 @@
1
+ // src/api/research.ts
2
+ //
3
+ // Web research — the direct (deterministic, non-agent) fetch+extract capability.
4
+ // Apps that just want a page's content/structured data call this rather than the AI
5
+ // agent loop (e.g. the Recipes app fetching a recipe's schema.org JSON-LD from a URL).
6
+ //
7
+ // Endpoints: /admin/collection/:collectionId/research
8
+ import { post } from "../http";
9
+ export var research;
10
+ (function (research) {
11
+ /**
12
+ * Fetch + extract a web page: clean markdown, page metadata, and any schema.org
13
+ * JSON-LD (filtered by `type` when given). Firecrawl-primary, cached per collection.
14
+ * POST /admin/collection/:collectionId/research/fetch
15
+ */
16
+ async function fetch(collectionId, body) {
17
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/research/fetch`;
18
+ return post(path, body);
19
+ }
20
+ research.fetch = fetch;
21
+ })(research || (research = {}));
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.17.0 | Generated: 2026-09-13T07:38:31.861Z
3
+ Version: 1.17.5 | Generated: 2026-09-13T17:21:14.684Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -57,6 +57,8 @@ For detailed guides on specific features:
57
57
  - **[Analytics](analytics.md)** - Web analytics, link-click tracking, QR/tag scan telemetry, and event reporting
58
58
  - **[Analytics Metadata Conventions](analytics-metadata-conventions.md)** - Standard recommended keys and conventions for analytics metadata fields
59
59
  - **[Loyalty: Points, Members & Earning Rules](loyalty.md)** - Loyalty schemes, automatic point earning via interaction rules, member balances, transaction history, and manual adjustments
60
+ - **[Integrations](integrations.md)** - Inbound/outbound integration flows + the sealed-secret store; triggers (manual/event/schedule), field mappings, and the Syndigo/Event Hub outbound path
61
+ - **[AI Tools & Skills](ai-tools-and-skills.md)** - The AI capability catalog: skills apps invoke by name (e.g. research.brand), the tools the AI reaches for (web fetch/screenshot/brand assets/image gen), the agent loop, and how apps discover them
60
62
  - **[Deep Link Discovery](deep-link-discovery.md)** - Registering and discovering navigable app states for portal menus and AI orchestration
61
63
  - **[AI-Native App Manifests](manifests.md)** - How AI workflows discover, configure, and import apps via structured manifests and prose guides
62
64
  - **[AI Guide Template](ai-guide-template.md)** - A sample for an app on how to build an AI setup guide
@@ -143,6 +145,7 @@ The Smartlinks SDK is organized into the following namespaces:
143
145
  - **order** - Functions for order operations
144
146
  - **products** - Functions for products operations
145
147
  - **realtime** - Functions for realtime operations
148
+ - **research** - Functions for research operations
146
149
  - **secrets** - Functions for secrets operations
147
150
  - **tags** - Functions for tags operations
148
151
  - **template** - Functions for template operations
@@ -1011,6 +1014,92 @@ interface AISearchPhotosPhoto {
1011
1014
  }
1012
1015
  ```
1013
1016
 
1017
+ **AgentRunRequest** (interface)
1018
+ ```typescript
1019
+ interface AgentRunRequest {
1020
+ input?: string
1021
+ prompt?: string
1022
+ instructions?: string
1023
+ model?: string
1024
+ maxSteps?: number
1025
+ allowCapabilities?: string[]
1026
+ only?: string[]
1027
+ exclude?: string[]
1028
+ }
1029
+ ```
1030
+
1031
+ **AgentToolResult** (interface)
1032
+ ```typescript
1033
+ interface AgentToolResult {
1034
+ name: string
1035
+ isError: boolean
1036
+ result: any
1037
+ }
1038
+ ```
1039
+
1040
+ **AgentRunResult** (interface)
1041
+ ```typescript
1042
+ interface AgentRunResult {
1043
+ finalText: string | null
1044
+ steps: number
1045
+ maxStepsReached: boolean
1046
+ toolResults: AgentToolResult[]
1047
+ availableTools: string[]
1048
+ }
1049
+ ```
1050
+
1051
+ **AgentToolDefinition** (interface)
1052
+ ```typescript
1053
+ interface AgentToolDefinition {
1054
+ name: string
1055
+ description: string
1056
+ capabilities: string[]
1057
+ parameters: any
1058
+ }
1059
+ ```
1060
+
1061
+ **AgentToolsResponse** (interface)
1062
+ ```typescript
1063
+ interface AgentToolsResponse {
1064
+ tools: AgentToolDefinition[]
1065
+ }
1066
+ ```
1067
+
1068
+ **AgentToolsQuery** (interface)
1069
+ ```typescript
1070
+ interface AgentToolsQuery {
1071
+ allowCapabilities?: string
1072
+ only?: string
1073
+ exclude?: string
1074
+ }
1075
+ ```
1076
+
1077
+ **SkillDescriptor** (interface)
1078
+ ```typescript
1079
+ interface SkillDescriptor {
1080
+ name: string
1081
+ description: string
1082
+ inputSchema: any
1083
+ outputSchema: any
1084
+ capabilities: string[]
1085
+ }
1086
+ ```
1087
+
1088
+ **SkillsListResponse** (interface)
1089
+ ```typescript
1090
+ interface SkillsListResponse {
1091
+ skills: SkillDescriptor[]
1092
+ }
1093
+ ```
1094
+
1095
+ **CatalogResponse** (interface)
1096
+ ```typescript
1097
+ interface CatalogResponse {
1098
+ tools: AgentToolDefinition[]
1099
+ skills: SkillDescriptor[]
1100
+ }
1101
+ ```
1102
+
1014
1103
  ### analytics
1015
1104
 
1016
1105
  **AnalyticsLocation** (interface)
@@ -7957,6 +8046,33 @@ interface AblyTokenRequest {
7957
8046
 
7958
8047
  **RealtimeChannelPattern** = `string`
7959
8048
 
8049
+ ### research
8050
+
8051
+ **ResearchFetchRequest** (interface)
8052
+ ```typescript
8053
+ interface ResearchFetchRequest {
8054
+ url: string
8055
+ type?: string
8056
+ schemaType?: string
8057
+ forceRefresh?: boolean
8058
+ }
8059
+ ```
8060
+
8061
+ **ResearchFetchResult** (interface)
8062
+ ```typescript
8063
+ interface ResearchFetchResult {
8064
+ provider: 'firecrawl' | 'web'
8065
+ status: number | null
8066
+ markdown?: string | null
8067
+ html?: string | null
8068
+ metadata?: Record<string, any> | null
8069
+ schemas: any[]
8070
+ url: string
8071
+ cached: boolean
8072
+ fetchedAt?: string
8073
+ }
8074
+ ```
8075
+
7960
8076
  ### segments
7961
8077
 
7962
8078
  **InteractionFilterValue** (interface)
@@ -8795,6 +8911,14 @@ interface Gs1DigitalLinkParams {
8795
8911
 
8796
8912
  ## API Functions
8797
8913
 
8914
+ ### agent
8915
+
8916
+ **run**(collectionId: string, body: AgentRunRequest) → `Promise<AgentRunResult>`
8917
+ Run the server-side AI agent loop once: assembles the tool set, runs the model, executes tool calls, and returns the final text + the tool trace. POST /admin/collection/:collectionId/ai/agent/run
8918
+
8919
+ **listTools**(collectionId: string, query: AgentToolsQuery = {}) → `Promise<AgentToolsResponse>`
8920
+ List the tools the agent can use (optionally scoped by capability / name). GET /admin/collection/:collectionId/ai/agent/tools
8921
+
8798
8922
  ### analytics.admin
8799
8923
 
8800
8924
  **summary**(collectionId: string,
@@ -10832,6 +10956,11 @@ Get an Ably token for public (user-scoped) real-time communication. This endpoin
10832
10956
  **getAdminToken**() → `Promise<AblyTokenRequest>`
10833
10957
  Get an Ably token for admin real-time communication. This endpoint returns an Ably TokenRequest that can be used to initialize an Ably client with admin permissions to receive system notifications and alerts. Admin users get subscribe-only (read-only) access to the interaction:{userId} channel pattern. Requires admin authentication (Bearer token). ```ts const tokenRequest = await realtime.getAdminToken() // Use with Ably const ably = new Ably.Realtime.Promise({ authCallback: async (data, callback) => { callback(null, tokenRequest) } }) // Subscribe to admin interaction channel const userId = 'my-user-id' const channel = ably.channels.get(`interaction:${userId}`) await channel.subscribe((message) => { console.log('Admin notification:', message.data) }) ```
10834
10958
 
10959
+ ### research
10960
+
10961
+ **fetch**(collectionId: string, body: ResearchFetchRequest) → `Promise<ResearchFetchResult>`
10962
+ Fetch + extract a web page: clean markdown, page metadata, and any schema.org JSON-LD (filtered by `type` when given). Firecrawl-primary, cached per collection. POST /admin/collection/:collectionId/research/fetch
10963
+
10835
10964
  ### secrets
10836
10965
 
10837
10966
  **list**(collectionId: string, query: ListSecretsQuery = {}) → `Promise<SecretList>`
@@ -10879,6 +11008,14 @@ Soft-delete a secret. DELETE /secrets/:ref
10879
11008
  **stats**(collectionId: string) → `Promise<SessionStatistics>`
10880
11009
  Get session statistics
10881
11010
 
11011
+ ### skills
11012
+
11013
+ **list**(collectionId: string) → `Promise<SkillsListResponse>`
11014
+ List the skills apps can invoke (name, description, input/output schema).
11015
+
11016
+ **run**(collectionId: string, name: string, input: Record<string, any> = {}) → `Promise<T>`
11017
+ Invoke a skill by name with structured input — the app-facing verb; no prompt-shaping. POST /admin/collection/:collectionId/ai/skills/:name/run
11018
+
10882
11019
  ### tags
10883
11020
 
10884
11021
  **create**(collectionId: string,
@@ -0,0 +1,180 @@
1
+ # AI Tools & Skills
2
+
3
+ The platform's AI can research the web, extract structured data, screenshot pages, and
4
+ generate images — through a **capability registry**. This page is the catalog: what the
5
+ AI can do, and how an app reaches for it. You should not need to call an API to find
6
+ this out — it's documented here so that when you build an app (or an AI assistant helps
7
+ you), you *know* these capabilities exist and can shape your app to use them.
8
+
9
+ ## Two layers: tools vs skills
10
+
11
+ - **Skills** are the app-facing verbs — named, composed capabilities with the
12
+ orchestration and prompt **baked in**. You invoke a skill by name with structured
13
+ input and get structured output back. **You never write a prompt.** Example:
14
+ `research.brand`.
15
+ - **Tools** are the atomic building blocks (fetch a page, generate an image). The AI
16
+ reaches for these *itself* during a skill or agent run — you rarely call them directly.
17
+
18
+ Rule of thumb: **if a skill exists for what you want, call the skill.** Drop to the
19
+ agent loop (below) only for open-ended tasks with no matching skill.
20
+
21
+ ## Using a skill
22
+
23
+ ```ts
24
+ import { ai } from '@proveanything/smartlinks'
25
+
26
+ // Research a client's brand from their website — no prompt, just input.
27
+ const { profile, sources } = await ai.skills.run(collectionId, 'research.brand', {
28
+ url: 'https://acme.com',
29
+ })
30
+ // profile → { name, description, tagline, palette:[{hex}], logoUrl, tone, keyProducts, socials }
31
+ // sources → which signals were available (markdown, branding, schema.org)
32
+
33
+ // Discover skills at runtime too (this catalog, live):
34
+ const { skills } = await ai.skills.list(collectionId)
35
+ ```
36
+
37
+ ## Deterministic extraction (no AI)
38
+
39
+ For structured pages, skip the LLM entirely — `research.fetch` returns schema.org
40
+ JSON-LD deterministically:
41
+
42
+ ```ts
43
+ const res = await ai./* research */ // see the `research` namespace
44
+ // or the tool directly inside an agent run: web.extractSchema
45
+ ```
46
+ (See the **Integrations / research** doc for `research.fetch`, used e.g. by the Recipes
47
+ app to pull a recipe's schema.org data without any AI.)
48
+
49
+ ## Open-ended tasks: the agent loop
50
+
51
+ When no skill fits, run the agent — it's given the tool catalog and reaches for tools
52
+ as your prompt warrants:
53
+
54
+ ```ts
55
+ const result = await ai.agent.run(collectionId, {
56
+ prompt: 'Research acme.com and draft a one-paragraph brand summary with 3 hero image ideas.',
57
+ allowCapabilities: ['web:read', 'ai:image'], // cap blast radius to these capabilities
58
+ })
59
+ // result.finalText + result.toolResults (the trace of tools the AI called)
60
+
61
+ const { tools } = await ai.agent.listTools(collectionId) // what the AI could reach for
62
+ ```
63
+
64
+ `allowCapabilities` gates which tools a run may use (e.g. omit `ai:image` to forbid
65
+ image generation). Capability tags are listed against each tool below.
66
+
67
+ ## How the AI discovers tools
68
+
69
+ Within a skill or `ai.agent.run`, the tool definitions (names, descriptions, JSON
70
+ schemas) are passed to the model, so it discovers and calls them automatically. Outside
71
+ a run — e.g. the plain chat endpoints — tools are **not** auto-injected; use a skill or
72
+ the agent loop to give the AI tool access.
73
+
74
+ ---
75
+
76
+ <!-- The section below is GENERATED from the server registry (single source of truth),
77
+ also served live at GET /admin/collection/:collectionId/ai/catalog.
78
+ Regenerate with `node scripts/gen-ai-catalog.js` in prove/server. -->
79
+
80
+ ## Skills
81
+
82
+ Named, composed capabilities an app invokes **by name** with structured input — no prompt-shaping. Call `SL.ai.skills.run(collectionId, name, input)`.
83
+
84
+ ### `research.brand`
85
+
86
+ Research a brand or company from its website URL into a structured brand profile (name, description, palette, logo, tone, key products, socials). Gathers page content + schema.org + branding deterministically, then synthesises with AI.
87
+
88
+ _Capabilities: web:read, ai:text_
89
+
90
+ **Input**
91
+ - `url` _(required)_ — string: The brand's website URL (https).
92
+ - `instructions` — string: Optional extra guidance for the researcher.
93
+
94
+ ## Tools
95
+
96
+ Atomic building blocks the AI reaches for **during** an agent/skill run — you rarely call these directly. Enumerable via `SL.ai.agent.listTools(collectionId)`; capability tags cap what a run may use.
97
+
98
+ ### `web.fetchPage`
99
+
100
+ Fetch a web page by URL and return clean markdown, page metadata, and any structured schema.org/JSON-LD data. Use to research a brand or product website.
101
+
102
+ _Capabilities: web:read_
103
+
104
+ **Parameters**
105
+ - `url` _(required)_ — string: Absolute URL to fetch (https).
106
+ - `type` — string: Optional schema.org @type filter for the returned JSON-LD, e.g. "Product" or "Recipe".
107
+ - `forceRefresh` — boolean: Bypass the cache and re-fetch.
108
+
109
+ ### `web.extractSchema`
110
+
111
+ Fetch a URL and return only its schema.org structured data (JSON-LD) of the given @type, e.g. "Recipe" or "Product". Deterministic — no AI.
112
+
113
+ _Capabilities: web:read_
114
+
115
+ **Parameters**
116
+ - `url` _(required)_ — string: Absolute URL to fetch (https).
117
+ - `schemaType` — string: schema.org @type to extract, e.g. "Recipe" or "Product".
118
+ - `forceRefresh` — boolean
119
+
120
+ ### `web.screenshot`
121
+
122
+ Capture a screenshot of a web page. Returns a stable hosted image URL (screenshotUrl) you can then read with image.describe.
123
+
124
+ _Capabilities: web:read_
125
+
126
+ **Parameters**
127
+ - `url` _(required)_ — string: Absolute URL to screenshot (https).
128
+
129
+ ### `image.describe`
130
+
131
+ Describe an image at a URL, or read text from it (image-to-text / vision). Use on a screenshot or photo to extract what it shows or says.
132
+
133
+ _Capabilities: ai:vision_
134
+
135
+ **Parameters**
136
+ - `imageUrl` _(required)_ — string: URL of the image to analyse.
137
+ - `prompt` — string: What to extract or describe (default: describe + transcribe visible text).
138
+
139
+ ### `brand.assets`
140
+
141
+ Extract a website's brand elements — logo, colours, design — plus page metadata. Use to research a brand's visual identity.
142
+
143
+ _Capabilities: web:read_
144
+
145
+ **Parameters**
146
+ - `url` _(required)_ — string: The brand's website URL (https).
147
+
148
+ ### `image.generate`
149
+
150
+ Generate a new image from a text prompt. Returns a stable hosted image URL (hostedUrl).
151
+
152
+ _Capabilities: ai:image_
153
+
154
+ **Parameters**
155
+ - `prompt` _(required)_ — string: Description of the image to generate.
156
+ - `size` — string: e.g. "1024x1024".
157
+ - `provider` — `openai` | `gemini`: Image model provider.
158
+
159
+ ### `image.fromReference`
160
+
161
+ Generate a new image guided by one or more reference images plus a prompt (image-to-image). Use to restyle, combine, or vary existing images. Returns a stable hosted image URL (hostedUrl).
162
+
163
+ _Capabilities: ai:image_
164
+
165
+ **Parameters**
166
+ - `prompt` _(required)_ — string: How to transform / what to create from the reference(s).
167
+ - `imageUrls` _(required)_ — array: Reference image URL(s) to guide generation.
168
+ - `size` — string: e.g. "1024x1024".
169
+ - `model` — string: Image model (default gpt-image-1).
170
+
171
+ ### `image.searchStock`
172
+
173
+ Search stock photography (Unsplash) for real photos matching a query. Returns candidate image URLs.
174
+
175
+ _Capabilities: web:read_
176
+
177
+ **Parameters**
178
+ - `query` _(required)_ — string: What to search for.
179
+ - `per_page` — number: How many results (default 10).
180
+ - `orientation` — `landscape` | `portrait` | `squarish`