Forge v0.17.1 — web_fetch and general file tools, org-wide command-denial platform policy (ASI02), and Kong AI Gateway auth
Forge v0.17.1 is a tools-and-governance point release for the open-source AI agent runtime. It gives agents two long-missing file-and-web capabilities — a web_fetch builtin that reads a URL as clean, LLM-readable markdown, and the previously-dormant file_read / file_write / file_edit / file_patch builtins now wired for every general agent — hardens the platform-policy surface with an operator-authored, org-wide command denylist (OWASP ASI02, Tool Misuse), and adds an apikey_header outbound LLM auth scheme so agents work behind Kong AI Gateway and other fixed-header API gateways.
All four ship on the v0.17.0 AARM (Autonomous Action Runtime Management) foundation. Every change is additive; see Upgrade notes for the two new default-on tools.
Highlights
web_fetchbuiltin — read a URL as clean text/markdown (#266). The "read this page" tool agents were missing:web_searchreturns results andhttp_requestreturns raw bytes, but neither reads a doc.web_fetchdoes a read-only GET over the same egress-controlled path ashttp_request(allowlist + SSRF protections, no new network path), converts HTML → clean markdown (strips nav/scripts/styling, preserves<pre>/<code>, transcodes non-UTF-8 charsets), enforces a content-type guard + redirect + size caps, and returns readable content plus the final URL. Default-on. See Tools & Builtins.- General file tools wired:
file_read/file_write/file_edit/file_patch(#268). Forge shipped four fully-implemented file builtins the runtime never registered — dead code reachable only from tests. They're now registered for every general agent, path-confined to the working directory (the samePathValidator#235 boundary the search tools use), giving a general agent a real file read/edit/overwrite surface instead of just search +file_create. Skipped when thecode-agentskill is active (its project-scopedcode_agent_*tools are the specialization — skill tools win). - Platform-layer
denied_command_patterns— org-wide, per-call command denial (#238, ASI02). Operators could deny at tool-name, egress-domain, and channel granularity, but had no argument-level control — so "keepcli_execute, but banrm -rf/git push --force/kubectl deleteacross the org" meant banning the whole tool or relying on per-skillSKILL.md. The new platform-policy field applies an operator-authored regex denylist to every tool call by any skill, matched atBeforeToolExec. It's the firstPlatformPolicyfield enforced per-invocation rather than once at startup, blocks emit an attributedguardrail_checkaudit event (source: platform), and an invalid regex fails closed at load. See Platform Policy — Runtime command denial. apikey_headerLLM auth scheme for API gateways (#302). Kong AI Gateway'skey-authplugin reads the consumer key from a fixedapikeyheader and ignores provider-native headers, so an agent pointed at a Kong-frontedOPENAI_BASE_URL/ANTHROPIC_BASE_URL401'd every call.model.auth_scheme: apikey_headersends the key in the gateway header in addition to the provider-native one (additive, safe against non-gateway endpoints), with an optionalauth_header_nameoverride for customkey_names.forge validaterejects an unknown scheme or a header name that collides with a native auth header. See Runtime Engine.
What's new
web_fetch builtin (#266)
web_fetch reads a specific page — a linked spec, changelog, or API reference — and returns it as clean markdown, so the model isn't hand-parsing raw HTML out of http_request.
{ "url": "https://example.com/docs/spec", "max_chars": 50000 }- Egress-controlled, read-only GET. Reuses
http_request's exact plumbing — the context egress transport,SafeRedirectPolicy, and the optional R9 JIT credential injector — so the allowlist / SSRF / DNS-rebinding protections and per-domain credentials apply identically. Fails closed: with no egress client installed it refuses rather than falling back tohttp.DefaultTransport. - HTML → clean markdown via
golang.org/x/net/html(no new external dependency): dropsscript/style/nav/footer/asidechrome; keeps the title, headings, list items, and links; preserves<pre>/<code>whitespace so code samples survive; transcodes non-UTF-8 charsets (older RFC/spec pages are often ISO-8859-1). - Guards & caps: content-type allowlist (refuses binary blobs — image / pdf / octet-stream), a redirect cap, a byte cap, and a
max_charscap (default 50 000) with a truncation marker. Returns{url, content_type, status, content, truncated?}; a non-2xx still returns the error page's content with its status.
General file tools (#268)
# Every general agent now has, path-confined to WorkDir:
# file_read — read a file (offset/limit) or list a directory
# file_write — create or overwrite a file
# file_edit — exact-string edit with a unified diff
# file_patch — batch add/update/delete/move in one callThere are two non-colliding file surfaces: the general file_* builtins (WorkDir-scoped, default-on) and the code-agent skill's project-scoped code_agent_* tools. When the code-agent skill is active the general builtins are skipped so the model never sees two overlapping surfaces. All four enforce the same directory-traversal confinement as file_create and the search tools.
Platform command denial (#238, ASI02)
# platform policy (system / user / workspace layer)
denied_command_patterns:
- pattern: 'kubectl\s+delete'
message: "destructive kubectl blocked by org policy"
- pattern: 'git\s+push\s+--force'
- pattern: '(^|\s)rm\s+-rf\b'Unioned across the three policy layers (first layer owns audit attribution). The match target is identical to skill deny_commands — cli_execute → the reconstructed command line, any other tool → the tool-input JSON plus its decoded string values (so a JSON-escaped separator like kubectl\tdelete can't dodge a whitespace pattern). The tool is not stripped (that's denied_tools); only matching calls are blocked, and a block emits a runtime guardrail_check event with source: platform + the offending pattern, layer, and message. Patterns compile at startup and forge validate --platform-policy rejects an invalid regex before deploy. Off unless a layer declares it.
apikey_header LLM auth (#302)
model:
provider: openai # or anthropic — symmetric
name: gpt-4o
base_url: https://kong-gateway.internal/openai
auth_scheme: apikey_header
# auth_header_name: x-gateway-key # optional; default: apikeyAdditive: the provider-native header (Authorization: Bearer / x-api-key) still rides, and the key is also sent in the gateway header, so the scheme is safe to enable against non-gateway endpoints. Extends the same auth_scheme extension point added for AWS Bedrock SigV4 in v0.16.0. Applies to the primary model only.
Upgrade notes
- Two new default-on tools change the general agent's tool surface. General (non-
code-agent) agents now registerfile_write/file_edit/file_patch(mutating, path-confined) andweb_fetchby default, alongside the existingfile_create. Both are confined to the working directory / egress allowlist respectively; action-level approval for mutating tools is tracked separately (#223). If you deny these for a given agent, add them to the policydenied_toolslist. - All other changes are additive and off by default.
denied_command_patternsdoes nothing unless a platform-policy layer declares it;apikey_headerdoes nothing unlessmodel.auth_schemeis set. No config changes are required to upgrade.
Full changelog
Full changelog: v0.17.0...v0.17.1