Chat
Harness tools
What each harness tool does, when it runs, what its results mean and its limits, in the chat, CLI, MCP and Research API.
The harness is the set of tools around the models. In the chat the model decides when to call them, and you see each call with its target and duration. Tool results reach the model wrapped in markers with a random id and labelled as untrusted content.
Server tools only read: public pages, search indexes, our mirrors and the files you attach. None of them scans, probes or sends a payload to a target. The CLI agent is the one part that runs commands, on your machine and with your approval.
When the chat offers each tool
| Tool | Offered when |
|---|---|
web_search, read_url | Web is on |
darkweb_search | Web is on and your message explicitly asks for it |
cve_lookup, cve_search, advisory_lookup | CVE is on |
kb_search, kb_read | Always. There is no switch |
file_list, file_read, file_search, binary_info, archive_list, disassemble | A file is attached |
A run stops at 12 model steps, 5 tool calls at a time, 60 seconds per tool and 10 minutes in total. Tool results enter the conversation and are billed as input tokens at the model's price.
Web search
web_search(query, count?) takes a query of up to 400 characters and returns titles, URLs and page excerpts, 5 results by default and 10 at most. Results from NVD, cve.org, CISA, GitHub, Seclists, PortSwigger and OWASP rank first, and identical queries are cached for 15 minutes. Results can be wrong or out of date, so open the source before you rely on it.
Reading a page
read_url(url) returns the text of one public page. In the chat it opens only URLs you typed or that a search, CVE, advisory or knowledge-base result returned. Links found inside a page and .onion results cannot be opened.
It accepts http(s) on ports 80 and 443 and HTML, text, JSON or XML, up to 10 MB and 15 seconds. Every address and redirect is checked, the connection is pinned to the checked IP, and robots.txt is honored. It refuses IP literals, attack strings, exposed-file paths such as /.git and /.env, and more than 40 distinct paths on one host in 10 minutes. A URL that carries text from an attached file is refused.
Dark web search
darkweb_search(query, max_results?, engines?) takes a query of up to 200 characters and returns up to 30 entries. Leave engines out to use every index.
The chat offers this tool only when you explicitly ask. Your message has to contain dark web, deep web, darknet, .onion, onion site, hidden service or Tor, or a direct follow-up to a turn that did. Portuguese and Spanish forms work too, and in other languages write those words in Latin letters. Naming a ransomware group or a leak is not enough, and those questions go to web_search. With Web off the tool stays off.
Each result is a search-index record: title, .onion URL, snippet and the index it came from. The harness reads the result pages of the indexes over Tor and never opens, crawls or downloads a listed page. Treat every entry as an unverified lead that may be hostile.
The limit is 5 searches per minute per user. Sponsored results are dropped. A safety filter refuses queries and drops results about child sexual abuse material. Without a Tor route the tool says so, and it may use one clearnet index instead.
Over MCP, calling darkweb_search is itself the explicit request. The Research API and the CLI have no dark web route.
CVE data
cve_lookup(id) returns one consolidated record: NVD description, CVSS 3.1 or 4.0 score and vector, CWE, affected CPEs with fix versions where NVD has them, references, EPSS score and percentile, and CISA KEV status with date added and known ransomware use. Each source shows when it was retrieved. A CVE with no CVSS reads as not scored and nothing is estimated. An ID the mirror does not have is fetched from the sources once.
cve_search(query?, vendor?, kev?, min_cvss?, min_epss?) returns up to 20 hits ranked by text match and EPSS. It asks NVD by keyword only when the mirror finds nothing.
Package advisories
advisory_lookup(name, ecosystem, version?) returns known vulnerabilities from OSV, up to 50. It reports what OSV lists for that name and version. Whether the vulnerable code is reachable in your build is yours to prove. Over MCP the tool is called advisory_query.
Knowledge base
kb_search(query, domain?, source?, tool?) searches the curated knowledge base and kb_read(id, from?, limit?) opens a document section by section. Domains are web, api, mobile, offensive, tools, cloud, ir and attack. Every hit carries its source, licence and attribution. A niche technique may not be there, and web search is the next step.
Files
The file tools read what the static parser extracted from an attachment. Nothing you upload is executed, and there is no dynamic analysis. Each file is parsed in a disposable gVisor container with no network, a read-only root and no secrets. A file over the limits or a parser failure ends as rejected with a reason.
| Tool | Returns |
|---|---|
file_list | Attached files with status, kind, size and warnings |
file_read(file_id, from?, limit?) | Extracted text by chunk, with a file and line locator |
file_search(query) | Chunks that contain your words, across every attached file |
binary_info(file_id) | SHA-256, size, entropy, and format, entry point, sections and imports for ELF and PE |
archive_list(file_id) | The archive's index |
disassemble(file_id) | A preview: the first 4 KB of the file decoded as x86-64, at most 200 instructions |
There is no decompiler and no control-flow graph. Archives stop at depth 3, 10,000 entries, 2 GB expanded and a 100:1 ratio. Text stops at 5 million characters per file. Images give dimensions only. The warning credentials_detected means the parser matched a key or token pattern. See Files in the chat for the file types.
Where each tool is available
| Capability | Chat | CLI | MCP | Research API |
|---|---|---|---|---|
| Web search | web_search | agent web_search | web_search | POST /v1/web/search |
| Page reader | read_url | read_url | POST /v1/web/read | |
| Dark web search | darkweb_search | darkweb_search | ||
| CVE record | cve_lookup | notholy cve, agent cve_lookup | cve_lookup | GET /v1/cve/{id} |
| CVE search | cve_search | notholy cve search | cve_search | GET /v1/cve/search |
| Package advisories | advisory_lookup | advisory_query | POST /v1/advisories/query | |
| Knowledge base | kb_search, kb_read | notholy kb, agent kb_search | kb_search, kb_read | GET /v1/kb/search, GET /v1/kb/{id} |
| File analysis | File tools above | notholy analyze | analyze_file | POST /v1/files |
| Local files and commands | Agent read, grep, glob, edit, write, bash | |||
| Engagement scope and log | notholy engage |
POST /v1/chat/completions, /v1/responses and /v1/messages are the raw model endpoints and have no harness tools. The model gets only the function tools you send, and your code runs them. To use this data from your own code, call the Research API or MCP.