|
1
|
--- |
|
2
|
name: image-search |
|
3
|
description: Find real web images, logos, and public photos for brand work, reports, and artifacts. Use when you need a few relevant results with a title and image URL you can inspect, present, or download. |
|
4
|
--- |
|
5
|
|
|
6
|
# Image Search |
|
7
|
|
|
8
|
Search the public web for real images. |
|
9
|
|
|
10
|
## When to Use |
|
11
|
|
|
12
|
- You need real logos, transparent PNGs, or brand assets from the web |
|
13
|
- You need real-world photos or reference images from the public web |
|
14
|
|
|
15
|
## When NOT to Use |
|
16
|
|
|
17
|
- Generating new images or illustrations (use the `media-generation` skill) |
|
18
|
- General fact lookup or webpage text retrieval (use the `web-search` skill) |
|
19
|
- Extracting brand colors, fonts, and other official tokens from a website (use `extractBranding` first) |
|
20
|
|
|
21
|
## Available Function |
|
22
|
|
|
23
|
### `imageSearch({ query, count })` |
|
24
|
|
|
25
|
Search for public web images and return the raw provider response body. |
|
26
|
|
|
27
|
**Parameters:** |
|
28
|
|
|
29
|
- `query` (str, required): Search text for the desired images |
|
30
|
- `count` (int, optional): Maximum number of results to return |
|
31
|
|
|
32
|
**Returns:** Dict with optional `results` list. For each result, rely on `result.title` and `result.properties?.url`; other provider-specific fields may also be present. |
|
33
|
|
|
34
|
**Example response:** |
|
35
|
|
|
36
|
```json |
|
37
|
{ |
|
38
|
"type": "images", |
|
39
|
"query": { |
|
40
|
"original": "mid-century chair", |
|
41
|
"spellcheck_off": false, |
|
42
|
"show_strict_warning": false |
|
43
|
}, |
|
44
|
"results": [ |
|
45
|
{ |
|
46
|
"type": "image_result", |
|
47
|
"title": "Mid-century chair in walnut", |
|
48
|
"url": "https://example.com/chairs", |
|
49
|
"source": "example.com", |
|
50
|
"page_fetched": "2026-04-17T23:51:41Z", |
|
51
|
"thumbnail": { |
|
52
|
"src": "https://imgs.example.com/thumb.jpg", |
|
53
|
"width": 500, |
|
54
|
"height": 333 |
|
55
|
}, |
|
56
|
"properties": { |
|
57
|
"url": "https://imgs.example.com/full.jpg", |
|
58
|
"placeholder": "https://imgs.example.com/placeholder.jpg", |
|
59
|
"width": 1200, |
|
60
|
"height": 800 |
|
61
|
}, |
|
62
|
"meta_url": { |
|
63
|
"scheme": "https", |
|
64
|
"netloc": "example.com", |
|
65
|
"hostname": "example.com", |
|
66
|
"favicon": "https://example.com/favicon.ico", |
|
67
|
"path": "› chairs" |
|
68
|
}, |
|
69
|
"confidence": "high" |
|
70
|
} |
|
71
|
], |
|
72
|
"extra": { |
|
73
|
"might_be_offensive": false |
|
74
|
} |
|
75
|
} |
|
76
|
``` |
|
77
|
|
|
78
|
**Example:** |
|
79
|
|
|
80
|
```javascript |
|
81
|
const response = await imageSearch({ |
|
82
|
query: "vintage travel posters", |
|
83
|
count: 6, |
|
84
|
}) |
|
85
|
|
|
86
|
const items = response.results ?? [] |
|
87
|
for (const item of items.slice(0, 4)) { |
|
88
|
console.log(item.title, item.properties?.url) |
|
89
|
} |
|
90
|
``` |
|
91
|
|
|
92
|
## Present Results |
|
93
|
|
|
94
|
When showing image results to the user: |
|
95
|
|
|
96
|
1. Pick up to 4 strong results |
|
97
|
2. Download each image URL into `attached_assets/image_search/` |
|
98
|
3. Call `presentAsset({awaitUserInput: false})` for each saved file |
|
99
|
|
|
100
|
```javascript |
|
101
|
const fs = await import('node:fs/promises') |
|
102
|
const path = await import('node:path') |
|
103
|
|
|
104
|
const response = await imageSearch({ |
|
105
|
query: "mid-century chair", |
|
106
|
count: 4, |
|
107
|
}) |
|
108
|
|
|
109
|
const items = (response.results ?? []).slice(0, 4) |
|
110
|
await fs.mkdir('attached_assets/image_search', {recursive: true}) |
|
111
|
|
|
112
|
for (const [index, item] of items.entries()) { |
|
113
|
const imageUrl = item.properties?.url |
|
114
|
if (!imageUrl) continue |
|
115
|
|
|
116
|
const download = await fetch(imageUrl) |
|
117
|
if (!download.ok) continue |
|
118
|
|
|
119
|
const filePath = path.join( |
|
120
|
'attached_assets/image_search', |
|
121
|
'result_' + String(index + 1) + '.jpg', |
|
122
|
) |
|
123
|
|
|
124
|
await fs.writeFile(filePath, Buffer.from(await download.arrayBuffer())) |
|
125
|
|
|
126
|
await presentAsset({ |
|
127
|
filePath, |
|
128
|
title: item.title ?? 'Image search result', |
|
129
|
awaitUserInput: false, |
|
130
|
}) |
|
131
|
} |
|
132
|
``` |
|
133
|
|
|
134
|
## When called from the slides skill |
|
135
|
|
|
136
|
The slides skill runs `imageSearch` as part of its brand-research steps in `../slides/references/brand_research.md`. That reference owns the order (run `extractBranding` first, use `imageSearch` for the logo only when the first step's logo is missing or low quality, and use `imageSearch` for real-world photos like product / team / venue shots) and the budget (at most 4 `imageSearch` calls per deck). |
|
137
|
|
|
138
|
**Specific real subjects have a special rule.** If `imageSearch` cannot find a clean image of a logo, a named person, a specific real product, a real team, a real venue, or a real event, leave the slot empty and surface the gap to the user. **Do NOT auto-generate a stand-in via `media-generation` without explicit user approval** — a fabricated logo or fake "real" photo for a named entity is exactly the failure mode the research steps exist to prevent. The `media-generation` fallback applies only to **generic, non-specific** visuals (abstract backgrounds, mood imagery, anonymous skylines, generic illustrations). In named-entity decks (product launches, founder profiles, company overviews) the deck subject often makes product, team, and venue slots specific — treat those as real subjects and leave them empty until the user approves a stand-in. Align with `../slides/references/brand_research.md` → "Failures". |
|
139
|
|
|
140
|
Follow these steps rather than improvising the order — these are billable passthrough calls. |
|
141
|
|
|
142
|
## Best Practices |
|
143
|
|
|
144
|
1. Use `imageSearch`, not provider-specific passthrough callbacks, so the implementation can change underneath without changing your code. |
|
145
|
2. For logos, search `"<company> logo png"` or `"<company> logo transparent"` and prefer official domains, press kits, or brand asset pages. |
|
146
|
3. Present a small shortlist of the best results instead of dumping the full response body. |
|
147
|
4. Use `extractBranding` first for official brand tokens, then fall back to `imageSearch` only when the logo is missing, low quality, or clearly wrong. |
|
148
|
5. Keep `count` small when you are manually reviewing results. `4` to `8` is usually enough. |
|
149
|
6. Save chosen image URLs into `attached_assets/` before presenting or reusing them elsewhere. |
|
150
|
7. Remember that `count` is the maximum number of results, not the total number of results. When presenting to the user, there may be less results presented than how many you requested. |