The ngrok engine: endpoints and Traffic Policy
Two decisions sit behind almost every ngrok task:
- What kind of endpoint? Agent, cloud, or internal - and on what protocol.
- What should happen to the traffic? The Traffic Policy that runs at the edge.
This skill answers both at the level a job skill needs, and holds the detail in
. Where to
apply the result is a separate question - see
.
Make these decisions from the user's intent. Do not ask them to choose an endpoint type; they should not have to know the taxonomy.
1. Endpoint type
- Agent endpoint - created by a running agent or SDK process, lives only as long as that process. Ephemeral, local, demos, tests.
- Cloud endpoint - created via API, dashboard, or IaC, independent of any agent. Always-on, stable URL. Production front doors, and anything a third party connects to on its own schedule.
- Internal endpoint - no public URL. Reachable only through a action. This is how a receiver stays off the public internet.
The composed shape most jobs land on:
cloud endpoint (public, runs the policy) -> forward-internal -> internal endpoint -> local service
Protocol is a separate axis from type. HTTP is the default; TCP (SSH, RDP, databases) changes several things - a public TCP endpoint needs a reserved address, internal TCP URLs need an explicit port, the policy phase becomes
, and the Kubernetes operator does not support TCP at all.
Full decision logic, bindings, and the TCP rules:
.
2. Traffic Policy
Rules grouped by phase. Each rule has optional CEL
and a list of
.
yaml
on_http_request:
- expressions:
- "req.url.path.startsWith('/admin')"
actions:
- type: deny
- Phases: , , , .
- Rules run in order, and a terminating action ends the chain. Every Cloud Endpoint policy must end with a terminating action; agent endpoints need not.
- The policy body is identical on every surface. Only attachment differs.
Grammar, CEL variables, Secrets and Vaults, the seven most-used actions, and how actions chain:
references/traffic-policy.md
.
The action vocabulary
All 26 actions, so you know what exists without fetching anything:
<!-- BEGIN generated: action-names -->
- connection modification: , , , , , ,
- request modification: , , , , , , ,
request-body-find-replace
, ,
- response modification: , , , , , ,
response-body-find-replace
, ,
- security: , , , , , , , ,
- traffic control: , , , , , , ,
<!-- END generated: action-names -->
Never guess an action's config. Look it up in two steps:
references/action-catalog.md
- the index. One row per action: phases, whether it ends the chain, what it does.
references/actions/<action>.md
- that action's config fields, result variables, and an example.
Read only the action file you need; the whole directory is ~12k tokens and one action is a few hundred.
Notes for agents
- The seven actions written out in
references/traffic-policy.md
are the ones existing job skills happen to use. They are not the interesting half - reach for the catalog whenever the task needs anything else.
- Many actions enforce on their own ( returns its own 429, fails closed). Check the action's entry before adding a that duplicates it.
- Keep the policy in its own so it survives the user adding a second surface later.
- If the ngrok MCP server is connected, run every policy you write or edit through
gw_validate_traffic_policy
before you show or apply it. It runs the same checks as a save, including plan entitlements, and reports each problem with its line and column. Pass , , and when the policy is for a cloud, TCP, or internal endpoint.