Skip to content

router: Move from Host header to explicit actor target header - #1333

Merged
Bowei Du (bowei) merged 4 commits into
agent-substrate:mainfrom
keithmattix:no-host-header
Sep 9, 2026
Merged

Bowei Du (bowei) merged 4 commits into
agent-substrate:mainfrom
keithmattix:no-host-header

Conversation

@keithmattix

@keithmattix Keith Mattix II (keithmattix) commented Aug 31, 2026 •

Copy link
Copy Markdown
Collaborator

This PR is purposefully controversial to try and encourage movement on the DNS issue (#445).

There has been an emerging consensus that substrate is not a system that we expect end-users to interact with directly; we can assume a higher-level orchestrator is acting on the user's behalf to program substrate. Therefore, our networking scheme does not need to use the Host header to encode an actor reference. This PR encodes that reference in one explicit routing header: ate-target-actor: <atespace>/<actor>. We expect the higher-order system originating substrate requests to set this header, removing the need for us to rewrite DNS. This also applies to actor-to-actor requests: atunnel originates CONNECT to the egress PEP, so when addressing another actor, it can set the routing header on the CONNECT request and the PEP can forward it to the router.

NOTE: CONNECT vs. direct HTTP (#1208) is a similar conversation; I see no reason not to lean 100% into CONNECT as the standard datapath for tunneling if we expect substrate to be controlled by a higher-order system. I only want to bite off one controversial issue at a time, so I'll save that for later.

Breaking change

Clients that previously selected an Actor with Host: <actor>.<atespace>.actors.resources.substrate.ate.dev must now send ate-target-actor: <atespace>/<actor>. The custom Actor DNS suffix is removed. Host and HTTP/2 :authority remain application metadata; CONNECT authority still carries the target host and port.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

@EItanya Eitan Yarmush (EItanya) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good to me overall. Just a few nits. Also I think we need to figure out how to message this to the community as it will definitely break existing demos and things.

Comment thread internal/resources/actor.go Resolved
Comment thread internal/e2e/suites/demo/demo_test.go Resolved
Comment thread internal/atunnel/ingress_test.go Resolved
Comment thread docs/threat-model.md Resolved
Comment thread docs/threat-model.md Resolved
Comment thread demos/egress/README.md Resolved
@bowei

Copy link
Copy Markdown
Collaborator

I think this needs to be discussed because the hostname-based integration is the simplest way for a system to integrate into being able to "send to a specific actor". There are a couple of topics that are somewhat independent:

  • Whether or not we actual serve DNS
  • How Actors discover each other
  • How external entities will address Actors

I would like to understand how this alternative ends up for our users.

Reference material:

@bowei Bowei Du (bowei) added area/network DO NOT MERGE This PR must not be merged yet. labels Sep 3, 2026
@bowei

Copy link
Copy Markdown
Collaborator

Add DO NOT MERGE for the discussion

@bowei Bowei Du (bowei) self-assigned this Sep 3, 2026
@keithmattix Keith Mattix II (keithmattix) changed the title router: Move from Host header to explicit headers for actor and atespace DO NOT MERGE: router: Move from Host header to explicit headers for actor and atespace Sep 3, 2026
@jeffmccune

Copy link
Copy Markdown

Keith Mattix II (@keithmattix) Thanks for organizing the call on Friday. Here's my take from the perspective of an operator of one of the higher order orchestrators the PR description mentions. Hopefully this helps close out the questions.

Note

Recommendation: one header, ate-target-actor: my-atespace/my-actor, sent to a host authority the orchestrator manages for the substrate.

Why one header? One header is preferred so that it's easier for me to check and set as simply as possible.

Why ate-target-actor? A header called just ate-actor is ambiguous about which end it names. x- headers are deprecated.

Why not the alternatives, from where I sit:

  1. Too onerous for operators. DNS/Host asks operators to change DNS they often don't own. I don't control our vanity domain; with this PR I need one record and one single-name cert for the router, plus an HTTPRoute.
  2. Too onerous on the agent-substate team. For example, requires substrate to own at least some portions of DNS, inviting conflict with other teams.
  3. Too onerous on everyone. Implicit, unclear, or shared ownership of the DNS boundary means everyone renegotiates it forever.

I'd be happy to add a little backwards compatibility shim to set the ate-target-actor header to avoid disrupting existing demos. The shim would accept requests like https://my-actor.my-atespace.actors.resources.substrate.ate.dev then forward the request to ate-router after dynamically setting the ate-target-actor header derived from the host header. This could be implemented with a simple ext_authz provider, (or many other alternatives TBD) which is how I prefer to handle authentication and authorization at the ingress Gateway anyway.

@keithmattix

Copy link
Copy Markdown
Collaborator Author

Jeff McCune (@jeffmccune) Appreciate the feedback! Agreed; one (non-X-prefixed) header is better in several ways

@keithmattix Keith Mattix II (keithmattix) changed the title DO NOT MERGE: router: Move from Host header to explicit headers for actor and atespace DO NOT MERGE: router: Move from Host header to explicit actor target header Sep 8, 2026
@bowei

Copy link
Copy Markdown
Collaborator

This is a follow-up to the discussion on 026-09-04:

  • I think this choice is not a 1-way door and it does not block future addition of DNS.
  • There are valid concerns about taking over a FQDN domain and TLS cert issuance due to two levels of wildcarding.

It would be good to be able to give users some "easy path" towards reaching their actors/agents. Mandating headers to be added is not possible with many clients without modification. We should keep a close watch on how many users end up building a shim anyway to use the system and incorporate the shim into Substrate if a common pattern emerges.

@keithmattix

Copy link
Copy Markdown
Collaborator Author

We should keep a close watch on how many users end up building a shim anyway to use the system and incorporate the shim into Substrate if a common pattern emerges.

Agree with this. I also think uid-based DNS is probably ideal as well, but there are concerns at the storage layer that shouldn't block this move

@EItanya Eitan Yarmush (EItanya) changed the title DO NOT MERGE: router: Move from Host header to explicit actor target header router: Move from Host header to explicit actor target header Sep 8, 2026
@EItanya Eitan Yarmush (EItanya) removed the DO NOT MERGE This PR must not be merged yet. label Sep 8, 2026
@EItanya

Copy link
Copy Markdown
Collaborator

Removed DO NOT MERGE from the title as we met and came to a joint conclusion, I will still not merge and wait for more input, but reviews should continue from here

@bowei Bowei Du (bowei) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks ok. Some comments.

Comment thread demos/jupyter/README.md
Substrate routes HTTP traffic using the `Host` header. To make this easy without modifying local `/etc/hosts` files, this demo includes a lightweight NGINX reverse proxy (`jupyter-proxy`) that automatically injects the proper `Host` header (`jupyter-notebook.ate-demo-jupyter.actors.resources.substrate.ate.dev`) and forwards traffic internally to the Substrate router.
Substrate routes HTTP traffic using `Ate-Target-Actor: <atespace>/<actor>`.
A browser cannot add that header to an address-bar navigation or WebSocket
upgrade, so this demo puts a lightweight NGINX reverse proxy (`jupyter-proxy`)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful about forcing all of our clients to do this.

Note: no action needed.

Comment thread docs/api-guide.md Resolved
Comment thread docs/threat-model.md

Substrate is an early, fast moving product. It is full of debate and subject to change, including major architectural changes. It also has little to no security hardening at this time. Therefore, this threat model is focused on how to achieve security with respect to the general problem Substrate is trying to solve: Fast orchestration of a stateful AI agents. The threat model uses Substrate's current implementation and roadmap as a reference point, but focuses on threats that emerge from this overall class of system, rather than threats specific to the current implementation.

# Intended Outcome

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this doc actually change a lot?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed; there are actually changes here, and I removed some of the whitespace to make that more obvious

Comment thread internal/atunnel/ingress.go Resolved
Comment thread internal/atunnel/ingress.go Resolved
Comment thread internal/atunnel/ingress.go Resolved
@bowei

Copy link
Copy Markdown
Collaborator

Thanks for the changes.

@bowei
Bowei Du (bowei) merged commit 0b3d2d0 into agent-substrate:main Sep 9, 2026
9 checks passed
John Howard (howardjohn) pushed a commit to agentgateway/agentgateway that referenced this pull request Sep 9, 2026
- [X] As required by the [Code of
Conduct](https://github.com/agentgateway/agentgateway/blob/main/CODE_OF_CONDUCT.md#generative-ai-policy),
the description, docs, and comments (words meant for humans) are written
by a human, not by an LLM.

agent-substrate/substrate#1333 removed the Host header parsing from
substrate, so this PR moves agentgateway to respect the new
`ate-target-actor` header.

---------

Signed-off-by: Keith Mattix II <[email protected]>
Eduardo Venegas (LaloVene) pushed a commit to LaloVene/agentgateway that referenced this pull request Sep 17, 2026
- [X] As required by the [Code of
Conduct](https://github.com/agentgateway/agentgateway/blob/main/CODE_OF_CONDUCT.md#generative-ai-policy),
the description, docs, and comments (words meant for humans) are written
by a human, not by an LLM.

agent-substrate/substrate#1333 removed the Host header parsing from
substrate, so this PR moves agentgateway to respect the new
`ate-target-actor` header.

---------

Signed-off-by: Keith Mattix II <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants