AI Agent Web Requests And Notes
What It Is
Every AI agent, assistant or builder, has a small set of tools of its own next to the tenant's MCP tools:
http_requestcalls an outside HTTP API or web page, with any method, headers and body.response_queryreads part of a response thathttp_requestsaved.notes_write,notes_readandnotes_deletekeep notes in the conversation's workspace.
They run in the AI Sidecar, not on the tenant's MCP server, so external MCP clients never get them. No setting turns them on: every agent has them in the chat and in agent runs.
Why It Matters
Many configuration tasks start from data that lives somewhere else. "Build a Country enumeration from the registry's API" or "map our CRM's pipeline stages to a status field" used to mean copying a response into the chat by hand. Now the person pastes the URL and the agent reads the API itself, looks at the parts it needs and builds the configuration from them.
Notes solve a different problem: a long conversation. Once a conversation outgrows the agent's conversation memory, its oldest part is summarised, and details such as record IDs, decisions or a half-finished plan can drop out. What the agent writes in a note is sent with every later turn of that conversation, however long it gets.
How It Works
http_request
The agent gives a URL and, optionally, a method (GET when omitted), headers, a body and a timeout. A body is sent as JSON, as a form (a=1&b=2) or as plain text; the agent can say which, or it is guessed from the body and the Content-Type header.
Every response is saved in the conversation's workspace under an id: r1, r2 and so on. What the model gets back depends on the size:
- A small body (up to about 12,000 characters) comes back whole, together with the status and headers.
- A larger body comes back as a preview, an outline of its structure (each object's fields with a sample value, each list's length) and the id to read it with
response_query. The model then reads only the parts it needs instead of the whole document. - A binary body (an image, a PDF) is described by type and size but not kept.
Everything a response contains is marked as coming from outside the platform: the agent is told to treat it as data to analyse, never as instructions to follow.
response_query
Reads a saved response without calling the API again:
- JSON: a JSONPath in
path($.data[*],$.items[0:20],$..id,$['odd key']),fieldsto keep only some fields of each match (dotted paths such asaddress.cityreach nested ones),whereto keep matches whose fields equal given values ({"active": true}; a list of values means any of them), andoffset/limitfor paging. Long results are cut to fit and say where to continue. - Text (CSV, XML, HTML): lines containing a text (
contains, case-insensitive) or a range of lines (start_line,line_count). - No arguments: the outline of the document.
Notes
notes_write saves a named note (plan, api-findings), replacing it or adding to it; notes_read reads one note or all of them; notes_delete removes one. Notes are Markdown.
In the chat, the notes and the list of saved responses belong to the conversation: they are sent to the model with every turn, and the person can read them, but not change them, under the Notes button in the chat's header, which appears once the conversation has any. In an agent run, notes and saved responses last only for the run.
Using a secret in a request
An API that needs a key gets it from the Secret Store, never from the chat. The agent writes {{secret:NAME}} where the key belongs: in a header (Authorization: Bearer {{secret:CRM_TOKEN}}), the query string or the body. The sidecar puts the value in just before sending, encoded for where it stands. The model never sees the value: if the API echoes the key back, the agent reads [secret:CRM_TOKEN] instead.
A secret can be used this way only after a Tenant Admin lists the hosts it may be sent to. A request that names any other secret, or sends a secret to another host, is refused before anything is sent. The system prompt lists the secrets an agent can use and their hosts, so people never need to paste keys into the chat.
Security Model
Anyone who can talk to an agent can ask it to call a URL, and a page or API response the agent reads can try to give it instructions. The rules below keep that from reaching what it should not:
- Public internet only. Requests may go only to public internet addresses. Names that resolve to the local machine, private networks, the cloud metadata service or other reserved ranges are refused, and the connection goes to the address that was checked, so a name that changes its answer cannot slip through. Each redirect is checked again.
- Secrets stay with their hosts. A secret is sent only to the hosts listed for it, never as part of a host name, and a request that carries one does not follow a redirect to another host. Authorization and cookie headers are dropped on any redirect to another host.
- External content is data. Responses are labelled as external, and the agent's instructions say to ignore instructions found in them and never to send the platform's data somewhere because external content asked for it.
- Everything is visible. Each call is a step in the chat (for example Call a web API · POST api.example.com/orders), recorded with the conversation's other tool calls; a call that is not a
GET,HEADorOPTIONScounts as a change in the reply's list of changes. The person can read every saved response's address and status under Notes. - Permissions do not change. What the agent may read or change in the tenant is still decided by its user and its tool scope. An outside API never widens it.
There is no allow-list of destinations for requests in general: a query string can carry data as well as a body can, so limiting methods or adding per-agent switches would not stop a determined misuse. Scope what the agent can read in the tenant instead, and list hosts only for the secrets agents really need.
Limits
| What | Limit |
|---|---|
| Time for one request, redirects included | 30 s, up to 60 s when the agent asks |
| Redirects followed | 5 |
| Response body kept | 5 MB (after decompression); the rest is cut and the response says so |
| Request body | 1 MB |
| Saved responses per conversation | the latest 30 |
| Notes per conversation | 30, up to 32,000 characters each and 128,000 together |
Example: An Enumeration From An Outside API
- A Tenant Admin stores the registry's API key in the Secret Store as
REGISTRY_TOKEN, with the hostapi.registry.example.com. - In a builder agent's chat: "Create a Country enumeration from https://api.registry.example.com/v2/countries, only the active ones, code as the item and name as the label."
- The agent calls the URL with
Authorization: Bearer {{secret:REGISTRY_TOKEN}}. The answer is large, so it gets an outline, sees$.data[*]withcode,nameandactive, and notes the plan. - It reads
$.data[*]withfields: ["code", "name"]andwhere: {"active": true}, page by page, and creates the enumeration and its items with the builder's model tools. - The person sees the steps, the changes made, and under Notes the plan and the saved responses.
Best Practices
- Give agents the secrets they need by host, not by pasting keys into a conversation or a system prompt.
- List exact hosts (
api.example.com) rather than wildcards (*.example.com) unless the API really spreads over subdomains. - Ask the agent to note its plan in long tasks; it keeps the thread when older messages are summarised.
- Keep builders scoped as before: a request to an outside API is one more source of input, not a reason to widen what the agent can change.