From e4a3d7cc0f1e4a0cd4a531846e0874be6c744845 Mon Sep 17 00:00:00 2001 From: Michael Mogenson Date: Tue, 24 Feb 2026 10:14:39 -0500 Subject: [PATCH 1/4] Fix large responses that break web_search tool The web_search tool frequently fails because the responses from the Brave Web API are too large to store and parse. When a response is larger than the 16k response buffer, the result is an incomplete JSON fragment that fails to parse. Fix this with two changes: 1. Provide a 'result_filter=web' filter parameter with the query. This omits Brave Web API results for news, videos, discussions, faqs, and other results that are not parsed by the web_tool. Only web results are returned. 2. Increase the response buffer from 16kb to 64kb. I ran a few queries and the max response size I saw was 58kb. There's two possible future optimizations not covered in this fix: Adding the "Accept-Encoding: gzip" header to received a compressed response. This would reduce the network traffic and required size for the response buffer. But, we'd still need a large internal buffer to inflate the response before parsing JSON. Next, most results from the Brave Web API have an 'extra_snippets' field which includes a summary of the result. This seems like useful additional context to provide to the agent. A web_search query for "Bitcoin price" now successfully returns the following response to the agent (tested by adding a debug log in the agent loop) ----------------------------------------------------------------------------- I (635063) agent: Tool web_search response: 1. Bitcoin price today, BTC to USD live price, marketcap and chart | CoinMarketCap https://coinmarketcap.com/currencies/bitcoin/ The live Bitcoin price today is $64,871.55 USD with a 24-hour trading volume of $45,314,283,881 USD. We update our BTC to USD price in real-time. Bitcoin is down 3.74% in the last 24 hours. 2. Bitcoin price today, BTC to USD live price, marketcap and chart | CoinDesk https://www.coindesk.com/price/bitcoin The price of Bitcoin (BTC) is $63,508.01 today as of Feb 24, 2026, 12:15 am EST, with a 24-hour trading volume of $24.62B. 3. Bitcoin BTC (BTC-USD) Live Price, News, Chart & Price History - Yahoo Finance https://finance.yahoo.com/quote/BTC-USD/ Bitcoin has a current supply of 19,993,606. The last known price of Bitcoin is 66,178.39249005 USD and is down -2.15 over the last 24 hours. It is currently trading on 12564 active market(s) with $39,417,837,545.32 traded over the last 24 hours. 4. Bitcoin Price Chart (BTC/USD) | Bitcoin Value | bitFlyer USA https://bitflyer.com/en-us/bitcoin-chart Check out the current Bitcoin (BTC) price, market cap, historical volatility, and buy Bitcoin on bitFlyer today with as little as $1! 5. Bitcoin Price | BTC to USD Converter, Chart and News https://www.binance.com/en/price/bitcoin Live price of Bitcoin is $96,262.14 with a market cap of $1,908.19B USD. Discover current price, trading volume, chart history, and more. --- main/tools/tool_web_search.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main/tools/tool_web_search.c b/main/tools/tool_web_search.c index d1b8ecf5..1af81af4 100644 --- a/main/tools/tool_web_search.c +++ b/main/tools/tool_web_search.c @@ -15,7 +15,7 @@ static const char *TAG = "web_search"; static char s_search_key[128] = {0}; -#define SEARCH_BUF_SIZE (16 * 1024) +#define SEARCH_BUF_SIZE (64 * 1024) #define SEARCH_RESULT_COUNT 5 /* ── Response accumulator ─────────────────────────────────────── */ @@ -254,7 +254,8 @@ esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t o char path[384]; snprintf(path, sizeof(path), - "/res/v1/web/search?q=%s&count=%d", encoded_query, SEARCH_RESULT_COUNT); + "/res/v1/web/search?q=%s&count=%d&result_filter=web", encoded_query, + SEARCH_RESULT_COUNT); /* Allocate response buffer from PSRAM */ search_buf_t sb = {0}; From 60d4757b45cc3e06f79ce85b63777da8c54f5ec2 Mon Sep 17 00:00:00 2001 From: Michael Mogenson Date: Tue, 24 Feb 2026 15:03:24 -0500 Subject: [PATCH 2/4] Log a warning when web search response data is dropped When needed >= sb->cap the incoming chunk is silently discarded, which surfaces later as a generic "Error: Failed to parse search results" with no indication that the response was truncated. --- main/tools/tool_web_search.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/tools/tool_web_search.c b/main/tools/tool_web_search.c index 1af81af4..a8d31517 100644 --- a/main/tools/tool_web_search.c +++ b/main/tools/tool_web_search.c @@ -35,6 +35,9 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) memcpy(sb->data + sb->len, evt->data, evt->data_len); sb->len += evt->data_len; sb->data[sb->len] = '\0'; + } else { + ESP_LOGW(TAG, "Response too large; dropped %d bytes (buf %zu/%zu)", + evt->data_len, sb->len, sb->cap); } } return ESP_OK; From f8925a3ec4276254b909e0a83d3531396d80cc1e Mon Sep 17 00:00:00 2001 From: Michael Mogenson Date: Tue, 24 Feb 2026 14:53:07 -0500 Subject: [PATCH 3/4] Reduce stack usage for web_search tool in direct mode In non-proxy mode, tool_web_search_execute allocates about 1.2kB on the stack, which is enough to cause a stack overflow on the console repl task. Replace the stack allocates for the query, path, and url buffers with a single heap allocation for a full url with query. Use static string literals with concatenated preprocessor defines to populate the url buffer. Encode the query at the end of the path template, since the Brave Web API allows the query parameter to be in any location. The proxy web search is even more problematic, since it allocates a 4kB response buffer on the stack. Fixing the proxy web search is out of scope for this commit. Before: ``` mimi> tool_exec web_search "{\"query\": \"Bitcoin price\"}"" I (110154) tools: Executing tool: web_search I (110154) web_search: Searching: Bitcoin price ***ERROR*** A stack overflow in task console_repl has been detected. ``` After: ``` mimi> tool_exec web_search "{\"query\": \"Bitcoin price\"}" I (359774) tools: Executing tool: web_search I (359774) web_search: Searching: Bitcoin price I (361114) web_search: Search complete, 1347 bytes result tool_exec status: ESP_OK ``` --- main/tools/tool_web_search.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/main/tools/tool_web_search.c b/main/tools/tool_web_search.c index a8d31517..b6466aff 100644 --- a/main/tools/tool_web_search.c +++ b/main/tools/tool_web_search.c @@ -17,6 +17,11 @@ static char s_search_key[128] = {0}; #define SEARCH_BUF_SIZE (64 * 1024) #define SEARCH_RESULT_COUNT 5 +#define STR(x) #x +#define XSTR(x) STR(x) + +static const char s_brave_url[] = "https://api.search.brave.com"; +static const char s_path_template[] = "/res/v1/web/search?count=" XSTR(SEARCH_RESULT_COUNT) "&result_filter=web&q="; /* ── Response accumulator ─────────────────────────────────────── */ @@ -250,20 +255,26 @@ esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t o ESP_LOGI(TAG, "Searching: %s", query->valuestring); - /* Build URL */ - char encoded_query[256]; - url_encode(query->valuestring, encoded_query, sizeof(encoded_query)); - cJSON_Delete(input); + /* Note: queries over 256 characters long are truncated */ + size_t query_len = strnlen(query->valuestring, 256) * 3 + 3; // worse case URL-encoding expansion + char *url = calloc(1, sizeof(s_brave_url) + sizeof(s_path_template) + query_len); + if (!url) { + cJSON_Delete(input); + snprintf(output, output_size, "Error: Out of memory"); + return ESP_ERR_NO_MEM; + } - char path[384]; - snprintf(path, sizeof(path), - "/res/v1/web/search?q=%s&count=%d&result_filter=web", encoded_query, - SEARCH_RESULT_COUNT); + /* Build Query */ + memcpy(url, s_brave_url, sizeof(s_brave_url)); + memcpy(url + sizeof(s_brave_url) - 1, s_path_template, sizeof(s_path_template)); + url_encode(query->valuestring, url + sizeof(s_brave_url) + sizeof(s_path_template) - 2, query_len); + cJSON_Delete(input); /* Allocate response buffer from PSRAM */ search_buf_t sb = {0}; sb.data = heap_caps_calloc(1, SEARCH_BUF_SIZE, MALLOC_CAP_SPIRAM); if (!sb.data) { + free(url); snprintf(output, output_size, "Error: Out of memory"); return ESP_ERR_NO_MEM; } @@ -272,12 +283,11 @@ esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t o /* Make HTTP request */ esp_err_t err; if (http_proxy_is_enabled()) { - err = search_via_proxy(path, &sb); + err = search_via_proxy(url + sizeof(s_brave_url) - 1, &sb); // just the path portion } else { - char url[512]; - snprintf(url, sizeof(url), "https://api.search.brave.com%s", path); err = search_direct(url, &sb); } + free(url); if (err != ESP_OK) { free(sb.data); From b03ae4c72d806afb62568f417e8e8cb9a34e4f71 Mon Sep 17 00:00:00 2001 From: Michael Mogenson Date: Fri, 27 Feb 2026 18:44:26 -0500 Subject: [PATCH 4/4] web_search: Increase header buffer for search_via_proxy() The function search_via_proxy still uses char header[512] with snprintf returning hlen, then passes hlen to proxy_conn_write. When hlen >= 512 (possible with longer encoded queries + 127-byte key), this reads past the stack buffer. Increase the header buffer size to 768. --- main/tools/tool_web_search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/tools/tool_web_search.c b/main/tools/tool_web_search.c index b6466aff..fe9daeef 100644 --- a/main/tools/tool_web_search.c +++ b/main/tools/tool_web_search.c @@ -176,7 +176,7 @@ static esp_err_t search_via_proxy(const char *path, search_buf_t *sb) proxy_conn_t *conn = proxy_conn_open("api.search.brave.com", 443, 15000); if (!conn) return ESP_ERR_HTTP_CONNECT; - char header[512]; + char header[768]; int hlen = snprintf(header, sizeof(header), "GET %s HTTP/1.1\r\n" "Host: api.search.brave.com\r\n"