Launch HN: Alter (YC S25) – Access control for multi-user agents

68 pointsposted 3 days ago
by simfinii

52 Comments

ianalloway1

a day ago

Curious how you handle actions with real-world cost versus plain read/write scopes. In my own agent experiments the useful controls were per-action spend caps, a rolling daily budget, and a human approval step above a threshold. Does Alter model 'this tool call spends money' as its own kind of permission, or is that left to the app?

kdodhia

a day ago

Hey! Kevan here. Yes, it's its own thing. We classify each provider's API operations into families, and "payment" (anything that moves money or changes billing) is one of them, so a rule can target payments without you listing endpoints.

On your three controls:

- Per-action caps: rules can match request params numerically, so "deny if amount > 5000" works today.

- Approval above a threshold: same matching drives human approval, e.g. "require approval on payments where amount > 1000". The approver sees the exact frozen request that will execute.

- Rolling daily budget: not built yet. Today we have per-agent quotas that count calls per minute/hour/day, but nothing that sums amounts across calls. We have the pieces (amount parsing per call, per-window counters, approvals), so it's a natural next rule type.

luis_valerio

2 days ago

One question from the infrastructure side (i'm running a similar scenario but for infrastucture) where any mistake could not be reversible such as a deletion of a resource.

How do you handle an agent that has valid authorization but has been prompt-injected?

kdodhia

2 days ago

Hey @luis_valerio, kevan here! That question shaped most of the design.

We assume you can't reliably stop the model from being prompt injected. So nothing is enforced at the model layer. Enforcement happens at the proxy, which sits between the agent and the downstream API and is the only thing holding the credential. The agent never sees the key, so an injected agent can't bypass it or route around the deterministic policy.

For irreversible actions you stack three things:

1. Method/endpoint restrictions. "This agent may only GET under /instances/*" means a DELETE never reaches the provider. For infra agents we'd push read-only by default and allowlist the few mutations you need.

2. Human-in-the-loop on the dangerous ops. Approval can be required conditionally: on DELETE, on specific operations, or when a parameter matches (resource outside the allowed set, etc). The request is frozen server-side, so what the approver sees is exactly what executes. The agent can't swap the payload after the yes.

3. Audit logs on every call, including denials, with the agent and end-user identity attached. So you can see the agent tried a DELETE it wasn't allowed, on whose behalf, and with what body.

Basically we treat every call like a compromised laptop: don't assume it behaves, scope the credential, and gate the risky actions behind a second party. Would love to hear more about your setup.

luis_valerio

a day ago

Hi, thanks for the detailed answer! Yes it's pretty similar to the approach we are following the only difference is that we cannot provide read permissions into the endpoint so we have some kind of compliance or auditor subagent that checks against forbidden actions and polices and as you mention also classify all the request in level of impact enforcing hitl for admins.

We are planning to do the policy check as much determistic as possible with OPA rules and so on, but we also have the policies in place at cloud level

kdodhia

a day ago

Makes sense. On not being able to get read-only creds from the endpoint: that's actually where a proxy helps most. A big part of what we've built is giving you fine-grained permissions even when the underlying provider doesn't have them. The key can be full-power, but the agent only ever reaches the API through the proxy, so "GET only under these paths" is enforced there and a write never reaches the provider even though the key could do it.

On the compliance subagent, the one thing I'd watch is that it reads the same untrusted context as the agent, so it can be injected too. We treat the model as advisory only. We have an AI review rule that rates a request's risk, but it can only escalate to a human approval. It can't deny, and it can't allow anything the deterministic rules didn't already allow, so a fooled reviewer costs you an extra approval, never a bad action. Your impact-level classification maps pretty directly onto that.

luis_valerio

a day ago

To be precise the thing provide permission to do any operation, including destructive actions to the agent but we do set policies, auth controls and hitl force approval to validate the destructive or high impact actions before apply them

Really good point about using the same context for the compliance, currently it's a separate subagent but read rules/policies and then check against the other agent proposal, no possible to inject since we control totally via a rail the prompt for the compliance subagent but it's true that it checks policies so it's not deterministic (works pretty well but not deterministic) so that's we are targeting checking that policies deterministically with OPA and then the compliance will only add to the final result some other checks that need to be LLM inferences.

So it's pretty similar to yours, you have any other additional harness to be as much determistic as possible?

kdodhia

a day ago

Yeah, sounds very close. The main thing we did to keep it deterministic is that nothing at request time is a model call. Rules are evaluated in the proxy against the actual request: method and path, the provider operation it maps to (we classify each provider's API into operations and families like delete or payment, from their published spec), parameter values, IP, time window, quotas. Default deny, and every rule can only narrow.

The other half is treating policy like code. Rules live in a file with test fixtures ("this request should be denied, this one should need approval"), `alter policy test` runs them, and `plan` / `apply` works like Terraform: you review a diff, and apply refuses if the plan was edited or the live policy changed since you reviewed it. `alter policy simulate` shows which rule fired for a given request and why.

luis_valerio

a day ago

Understood yeap. Yes exactly is terraform/opentofu. The point is that we cannot do it at proxy level since we do allow any kind of operation attempt (we just filter that it's an infra req), then we generate the code based on the policy and, as you mention, once we have a validated plan we crosscheck against the compliance checker and provide an assessment about criticity and policy compliance...and trigger an automatic hitl for admin if needed otherwise it allows approve the pr an apply afterwards

kdodhia

17 hours ago

Makes sense, sounds like a solid setup. If your agents ever start calling cloud/internal APIs directly instead of going through the PR flow, that's exactly what we built Alter for, and we'd love to help. Either way, good luck with it!

ZukiniPie

8 hours ago

what does the agent do while it’s waiting on the approval to happen?

kdodhia

5 hours ago

It doesn't sit there blocked. The call comes back right away with a pending status and an approval id, so the agent can tell the user "this needs sign off from X" and get on with other stuff. Then you either await it inline with a timeout or stash the id and have a worker poll it later. Once it's approved we run the exact request that was approved and the agent gets the provider's response back. If nobody answers in time it expires (10 min by default, you can set it up to 24h) and the agent has to make the call again.

advism2

a day ago

Related question on irreversible actions: how do you handle retries after a call has been approved? If the agent or the network retries a non-idempotent request (a payment, a delete), does the proxy guarantee at-most-once execution, e.g. with an idempotency key bound to the approval? In my experience, duplicate execution after approval is as dangerous as the unapproved call itself.

kdodhia

a day ago

Approved calls run at most once. Execution is claimed atomically so two workers can't both run it, and if the agent re-sends the same call it doesn't re-run the approved one, it creates a new approval that needs its own yes. If the provider call fails before the request ever left (connection refused, DNS) we retry. If it might have reached the provider, like a timeout on a POST, we don't resend. The approval fails as "outcome unknown" so someone checks the provider instead of guessing. Agree a duplicate after approval is as bad as no approval.

ZukiniPie

8 hours ago

but how does the person doing the manual check actually find out it’s sitting there waiting on them?

kdodhia

5 hours ago

When approval is needed the agent gets a link back for each approver, and most people just push that wherever their team already lives, a Slack DM, an in-app notification etc. We can also email the approver directly if the policy is set up with email notifications. The link itself doesn't approve anything, the approver has to sign in and only the person designated as approver can even open it. Then they see the full request that's going to run and approve or deny it

snarkytables

a day ago

Does the design have a hard constraint that the agent reaches downstream APIs only through a proxy? (Ref from another comment: Enforcement happens at the proxy, which sits between the agent and the downstream API)

What happens if the agent agent can bypass the proxy?

kdodhia

17 hours ago

Yup, the constraint isn't on the network, it's on the credential. The provider token or API key lives in our vault and the agent never sees it. All the agent holds is an Alter key, and the only thing that key can do is ask us to make a call. We check policy against the actual request, inject the credential and send it ourselves

So say the agent goes around us and hits the API directly. It has nothing to authenticate with, and the provider returns a 401. It also can't use us to leak the credential: for API-key credentials, we only inject them into requests going to hosts you've allowlisted for that provider, so pointing the call at its own server gets blocked before the key is attached.

To make it airtight, mint the agent's Alter key with proxy-only permission. We also have a mode where the SDK fetches the token for each call, but that's a separate permission and a proxy-only key can't use it.

Where it does break down is credentials we don't hold. If someone leaves a personal API key in the agent's environment, the agent can use it directly and we'll never see that traffic. Locking down outbound network access closes that gap, but that's on your infra side.

snarkytables

15 hours ago

I couldn't find it in your docs. Do you have mTLS authentication from agent to proxy ?

kdodhia

5 hours ago

Not today, no. Right now it's TLS plus the agent's Alter key, and every request is signed with that key. Each signature is timestamped and single use, so a captured request can't be replayed or tampered with. You can also lock a key to specific IP ranges, scope it down to just what that agent needs, and give it an expiry, so a leaked key is pretty limited in what it can do and where from. mTLS is a fair ask though, especially for people running agents in their own infra, and it's something we'd look at adding

souvik1997

3 days ago

Looks cool!

One aspect of multi-user agent security, which I think is underexplored, is how context from a higher-privileged session might "leak" into a lower privileged session. Suppose the CEO of a company uses your shared openclaw agent and the agent writes sensitive data (investor emails, for example) to its memory. My understanding is this is not protected by Alter. Then a contractor uses the same agent and can read that same memory. It seems to me that a better agent harness for this kind of multi-user use case is needed; the standard ones like openclaw and claude code simply are not designed for it. Would love your thoughts!

simfinii

2 days ago

We actually account for this already! We allow developers to use alter to partition context memory based on end user + agent identity so the context leaks like the one you described can be fully prevented!

Feel free to go through the docs here if you have more questions: https://docs.alterauth.com/guides/propagate-identity-to-memo...

Melatonic

2 days ago

Seems like this could be very useful for more than just security !

simfinii

2 days ago

Thank you! Yes the goal is to allow developers to build multi-tenanted agents that can actually act on behalf of end users. We are in the process of abstracting away every building block needed to build that so developers can focus on what they do best

souvik1997

2 days ago

Amazing! Great to hear you've already thought about this

ptkachykby

2 days ago

You can add a tag to each memory indicating who wrote it, and then at read time filter the memories instead of putting them in the prompt.

I am the founder of Substrate, a project that lets you inspect what is in the memory and select what each agent sees.

Do you separate memory per user with your harness?

simfinii

2 days ago

Yes we do. We separate based on both the end user identity and agent identity. Would love to see how your product could potentially work with alter

ptkachykby

a day ago

Cool. Followed you on X. Would you mind replying there?

user

2 days ago

[deleted]

avikonduru

2 days ago

How do you handle permissions when the downstream service only offers a shared API key? For example, two sales reps can use the same CRM endpoint but should only access their own accounts. Does Alter check record ownership, or does the developer still need to supply that logic?

heyvaldemar

a day ago

Measured on an agent I run, before it knew whose request it was serving: 7 of 10 checks failed. Acting for an account manager, another manager's customer record came back in full. Acting for first-line support, who may not send email, it sent one. What fixed it was putting the ownership rule at the one door every call goes through, the tool server, not in the records service, which only ever sees the server's key. Every call carries two tokens, the agent's and the person's, both checked by the API server.

The agent may do only what both are granted, and a customer outside the person's own is answered exactly like one that does not exist, so nobody can enumerate by asking. The gap I still have: the model gateway behind it knows only the agent, so one person can spend the whole agent's token budget.

simfinii

2 days ago

We allow end users to add API keys directly via the alter connect SDK. If the API key needs to be shared then developers can map it on their end using the grant ID abstraction that we provide. Feel free to go through the docs here: https://docs.alterauth.com/concepts/credentials/

verdverm

2 days ago

> We allow end users to add API keys directly

This seems like a bad idea to me these days. Companies doing this make themselves a target and then get hacked like OpenCode. Customer accounts get drained or bills run up.

Run your own gateway behind a firewall / vpn. I personally use GoModel + Tailscale.

https://news.ycombinator.com/item?id=50133401 (OpenCode hacked story)

kdodhia

17 hours ago

Yeah we've put most of our effort so far into security, this part especially. Keys are encrypted in a dedicated secrets vault and once saved nobody can read them back, not even the dev who set them up. In proxy mode the key never even reaches the agent, we inject it on our side and only into requests going to hosts that are allowlisted for that provider. Every use gets checked against policy and logged with who used it and on whose behalf

Every change we ship gets scanned for supply chain attacks and goes through static code scanners too. We've been pen tested by two separate firms and we're in the observation period for SOC 2 type 2, details are at trust.alterauth.com. We're also planning open sourcing the full platform soon so you'll be able to look at the code yourself.

yaoke259

2 days ago

what's the advantage of a tool like this compared to existing mature tools like infisical?

simfinii

2 days ago

Great question! If you are looking to just store secrets you can just use infisical.

The real value of alter comes in when you want to give your agents access to end users credentials. When agents act on behalf of end user as a developer you have to manage multiple credentials and more importantly manage the mapping relationship between end user identity and the credentials.

Also, as agents take actions the problem of non deterministic actions become more pronounced. With alters policy guardrails any chance of actions taking negative actions is mitigated.

Lastly, the full compliance trails of what the agent has done ends up being quite valuble especially as agents take more autonomus actions!

jeswin

2 days ago

This might seem like an aggressive question. But it's one to be asked of products dealing with auth.

For a security-centric product, how would I trust your fully vibe-coded product if I can't see the source code?

simfinii

2 days ago

Hey! Fair question.

We are currently in the process being fully SOC2 compliant and have gotten pen tested twice from two different companies and have found no issues. You can explore the full extent of our security process and pen test results here : trust.alterauth.com

Separately would say it is a bad assumption to make that a product is vibe coded without trying it out. As mentioned in the post we adopted a lot of security processes as a part of our SDLC including consistent scans for supply chain attacks, and static code scanners (SAST).

We also do a pen test at a yearly cadence

jeswin

2 days ago

> Separately would say it is a bad assumption to make that a product is vibe coded without trying it out.

You've put it behind a very typical AI-generated UI; like the many that come up every day. In your case, it's an auth product and it matters more. Besides, It's difficult to try your product without handing you the keys to the kingdom.

> We are currently in the process being fully SOC2 compliant

You're getting a Type I attestation first, I presume? That is of limited value in itself, and is mostly about getting to Type II. If you already have Type I complted, you could mention that on the website. "Regulated industries" have long sales cycles and evaluations, and you'll find it difficult to start those conversations without a more reassuring website.

simfinii

a day ago

We are open sourcing the full platform soon so you will be able to inspect the the code.

Regarding SOC2, in the process of getting SOC2, Type 2 compliant. As you may know there is 3 month waiting period before the auditors give a SOC2 certification so currently in the waiting period for that

911viper

2 days ago

[flagged]

simfinii

2 days ago

When several principals are in the same channel talking to the same agent the concept of agent delegation does not apply.

The right way to treat the agent is not as a delegated agent but rather as a stand alone agent with its own permissions and privleges.

In scenarios where an agent and humans are peers we recommend giving separate agent identities to the agent and treat them as separate privileged users and give them permissions based on their identity and not based on the identities of the users in the channel.

We support standlone agent identities that dont require end users as the principals. Can read about that here: https://docs.alterauth.com/guides/give-an-agent-scoped-acces...

mauvehed

2 days ago

That website is literally a vibe-coded template.. How can we put any trust into the app itself?

simfinii

2 days ago

We are in the process of getting SOC2 compliant. You can go through our trust page here: https://trust.alterauth.com/

We have also gotten pen tested 2 separate times and have found no issues. You can find the result of one of the pen tests on the trust center

sirianni

2 days ago

  is this an LLM generated response. The irony…

simfinii

2 days ago

LOL that was a polite response to a rude question. There was no LLM involved there