1 # Brave
2
3 Proxy requests to Brave via Replit-managed billing.
4
5 ## Callback
6
7 Use `externalApi__brave` in `code_execution`.
8
9 ## Allowed operations
10
11 - `GET` `/res/v1/images/search/*?` - Brave Image Search
12
13 Authorization is handled automatically by Replit. Do not pass an `Authorization` header.
14
15 ## Skill
16
17 ## Brave image search
18
19 Search real web image results through Brave passthrough billing.
20
21 ### When to use
22
23 - The user asks for real-world images from the web
24 - You need image URLs to support analysis, reports, or artifacts
25
26 ---
27
28 ## Callback quickstart
29
30 Use `externalApi__brave` with this allowed operation:
31
32 - `GET /res/v1/images/search`
33
34 Put URL params in `query`.
35
36 ```javascript
37 const result = await externalApi__brave({
38 path: '/res/v1/images/search',
39 method: 'GET',
40 query: {q: 'vintage travel posters', count: '6'},
41 })
42
43 const items = result.body?.results ?? []
44 for (const item of items) {
45 console.log(item.title, item.properties?.url)
46 }
47 ```
48
49 Common response paths:
50
51 - Image URL: `body.results[i].properties.url`
52 - Title: `body.results[i].title`
53
54 Authorization is managed by passthrough billing. Do not set an
55 `Authorization` header manually.
56
57 ---
58
59 ## Render Brave images in chat
60
61 For chat panel rendering, use the `media-generation` skill flow:
62
63 1. Select up to 4 relevant results
64 2. Download each URL to `attached_assets/brave_images/`
65 3. Call `presentAsset({filePath, title})` for each saved file
66
67 ```javascript
68 const result = await externalApi__brave({
69 path: '/res/v1/images/search',
70 method: 'GET',
71 query: {q: 'mid-century chair', count: '4'},
72 })
73
74 const items = (result.body?.results ?? []).slice(0, 4)
75
76 for (const [index, item] of items.entries()) {
77 const imageUrl = item.properties?.url
78 if (!imageUrl) continue
79
80 const filePath =
81 'attached_assets/brave_images/result_' + String(index + 1) + '.jpg'
82
83 // Imports, fetch, and file writes are impure — keep them inside the
84 // "use impure" boundary. externalApi__brave and presentAsset are
85 // callbacks and must stay in durable scope.
86 const saved = await (async function (url, out) {
87 "use impure";
88 const fs = await import('node:fs/promises')
89 const path = await import('node:path')
90 const response = await fetch(url)
91 if (!response.ok) return false
92 await fs.mkdir(path.dirname(out), {recursive: true})
93 await fs.writeFile(out, Buffer.from(await response.arrayBuffer()))
94 return true
95 })(imageUrl, filePath)
96
97 if (!saved) continue
98
99 await presentAsset({
100 filePath,
101 title: item.title ?? 'Brave image',
102 })
103 }
104 ```
105
106 ## Example
107
108 ```javascript
109 const result = await externalApi__brave({
110 path: '/res/v1/images/search/*?',
111 method: 'GET',
112 query: {},
113 })
114
115 console.log(result.status)
116 console.log(result.body)
117 ```