network
Audit agent network egress to find risky outbound requests. Scans web tool calls to reveal targets and flag risks like plain HTTP, credentials, or secrets in URLs.
Instructions
Network-egress audit — the network preset (F4.3).
One call answers "where did an agent reach out to the network — and
how risky did those requests look?". A preset over the existing core,
not a second engine: ONE query scan (type="tool_call",
tool_kind="web") supplies the candidates — Claude
WebFetch/WebSearch, OpenCode webfetch, Codex web_search
(surfaced from web_search_call rollout records),
Gemini/Antigravity web_fetch/google_web_search; Pi records no
web tool (honest absence). The request target (url/query) is
extracted from each call's own input and assessed with a deterministic
risk dictionary: plain_http, credentials_in_url,
secret_in_url / secret_in_query (the redaction patterns double
as the detector), ip_literal_host, private_or_local_host,
punycode_host. Zero LLM, zero guessing: no extractable target →
honest null fields; a risk fires only on parse/regex evidence.
Filters (all parameters): agent, session (uuid or list of
uuids), since/until (ISO bounds on the call ts), kind
(fetch|search — derived from the extracted fields, unknown
values fail loud), risk (include default | only |
exclude), domain (host equals-or-subdomain match), noise
and project_dir (session-level, same semantics as query).
Each request record carries the query event id (walk its context
via query(relative_to=...) / read_session), the derived
kind, char-capped url/query (token budget — full context
stays on-demand), domain, the risks labels and tri-state
is_error (null when the agent's format has no correlated
outcome signal — honest, cross-agent). count/risky_count/
by_domain/by_risk always reflect the FULL match set; limit
(default 50, 0 = no cap) bounds only the emitted records
(truncated).
Honesty caveats (documented, not hidden): risk labels are a
deterministic dictionary, not a threat oracle; MCP-mediated network
access (browser-automation servers etc.) stays under
tool_kind="mcp" — a name alone cannot prove an MCP server touches
the network, so it is never guessed into this audit. Risk assessment
runs on the RAW stored strings; redact=true (default) masks
secrets only in the emitted url/query/session_title fields
(redactions type→count dict when anything was masked). When
count == 0 the response carries diagnostics so an empty result
is explainable.
Thin wrapper over :func:ai_r.network.network that translates the
core ValueError contract into the {"error": "invalid_argument", "message": str(exc)} shape the MCP client expects.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | ||
| risk | No | include | |
| agent | No | ||
| limit | No | ||
| noise | No | include | |
| since | No | ||
| until | No | ||
| domain | No | ||
| redact | No | ||
| session | No | ||
| project_dir | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||