Repository navigation
[FEATURE] Credential headers on Agent egress entries #3093
Description
Problem
#3019 lets an Agent reach extra origins, but not authenticate to them. kagent binds gateway credentials only for ModelConfig keys and RemoteMCPServer headers.
Proposal
Make Agent.spec.egress entries objects, with optional headers the egress gateway sets. The runtime sends each header with a placeholder and never holds the value.
spec:
egress:
- origin: https://proxy.golang.org # reach only, as in #3019
# A Secret's value
- origin: https://api.internal.example
headers:
- name: Authorization
prefix: "Bearer "
valueFrom:
secretKeyRef: {name: internal-api, key: token} # OAuth 2.0 client credentials
valueFrom:
oauth2:
tokenURL: https://auth.example/oauth/token
audiences: [https://api.internal.example]
scopes: [read]
clientAuth:
method: clientSecretPost
secretRef: {name: internal-api-client} # client-id, client-secret # On-Behalf-Of: the caller's token exchanged for this API (RFC 8693)
valueFrom:
oauth2:
tokenURL: https://auth.example/oauth/token
audiences: [https://api.internal.example]
clientAuth:
method: clientSecretPost
secretRef: {name: internal-api-client}
tokenExchange:
subject: Callerheadersonly on exacthttpshosts, where Substrate injects.valueFromis a union, so new sources don't change existing Agents.- A missing Secret is reported on
ResolvedRefs.
secretKeyRef works with Substrate as is. oauth2 needs a Substrate credential provider that runs the grant and caches tokens (as kagent-dev/substrate#47 does for Google). On-Behalf-Of also needs kagent to pass each turn's caller token to that provider.
Alternative: a separate EgressEndpoint resource
Define the origin and its headers once, in their own resource, and have Agents reference it by name, the way they reference a ModelConfig:
kind: EgressEndpoint
metadata: {name: internal-api, namespace: team-a}
spec:
origin: https://api.internal.example
headers:
- name: Authorization
prefix: "Bearer "
valueFrom:
oauth2: {...} # same sources as above
---
kind: Agent
spec:
egress: [https://proxy.golang.org] # #3019, unchanged
egressEndpointRefs:
- name: internal-api # its origin is opened automaticallyThis is safer for a platform. With headers on the Agent, anyone who can write an Agent can bind any Secret in the namespace to any host they list. With a separate resource:
- Platform owners decide where each credential may go, and with what scopes. Agent authors can only pick from those endpoints.
- Kubernetes RBAC can split the two: create on
EgressEndpointfor the platform, onAgentfor users. kagent's API and UI would manage Agents but not endpoints, so the split holds even though the API authorizes no one. - One endpoint serves many Agents, and changes to where credentials go are reviewed in one place.
- feat(api): Agent.spec.egress — HTTP(S) origins an Agent may reach #3019's
egressstays a list of strings.
Later, an endpoint could also limit which Agents may reference it (for example by label), like Gateway API's ReferenceGrant.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsBacklog
Activity
[-][FEATURE] Secret-backed headers on Agent egress entries[/-][+][FEATURE] Credential headers on Agent egress entries: Secrets, OAuth client credentials, On-Behalf-Of[/+][-][FEATURE] Credential headers on Agent egress entries: Secrets, OAuth client credentials, On-Behalf-Of[/-][+][FEATURE] Credential headers on Agent egress entries[/+]feat(api): Secret-backed headers on Agent egress entries
feat(api): Secret-backed headers on Agent egress entries
feat(api): Secret-backed headers on Agent egress entries
feat(api): Secret-backed headers on Agent egress entries
fiunchinho commentedon Oct 8, 2026
+1 for the
EgressEndpointalternative.ModelConfigandRemoteMCPServereach hold a destination and its credentials, and an Agent references them by name. AnEgressEndpointwould be the same kind of resource for any other HTTPS destination.Agent.spec.egressfrom feat(api): Agent.spec.egress — HTTP(S) origins an Agent may reach #3019 stays a list of strings for hosts that need no credentials.ModelConfigkeys and Secret-backedRemoteMCPServerheaders into destination-scoped bindings that Substrate's gateway injects (docs/architecture/credential-injection.md). A first version withsecretKeyRefheaders could reuse that path, andoauth2could follow once Substrate has a provider for it.A few points I think a first version should settle:
ModelConfig, aRemoteMCPServeror another endpoint on the same Agent should fail compilation with a clear error.allowedNamespaces, asRemoteMCPServerdoes.ResolvedRefsof the endpoint, and an unresolvedegressEndpointRefsentry on the Agent's conditions.@thomasbarrett are you planning to implement this? If not, I'm happy to pick it up once #3019 lands. It would be good to hear from the maintainers whether a new CRD is the direction they want before either of us starts.
thomasbarrett commentedon Oct 8, 2026
I was planning on implementing this on Fluidstack internal fork to test on some of our agent workloads and contributing upstream, but would love help @fiunchinho . I'm going to pull up to community meeting next week to discuss
thomasbarrett commentedon Oct 8, 2026
Another consideration is that we likely want authenticated egress from Sandbox actor as well so that the agents can upload and download files to S3, internal / external services etc.
feat(api): Secret-backed egress headers for Agents, and egress for Sa…