kdodhia
Joined 3 years ago
Joined 3 years ago
short answer is no, the policy engine doesn't know where an argument came from across calls. each call is judged on its own: which agent, which end user it's acting for (plus the delegation chain), which grant, which operation and the params on the request. so in your example the contractor's send passes if their policy allows it
we put the controls at the two ends instead of following the data through the middle - write side: the CEO's grant posting into a shared channel is its own call, so you can require approval for it or just deny it - send side: we parse sends into recipients, so a contractor can be limited to emailing inside the company domain, or anything external needs a human approval on the exact frozen request
every call is audited with the agent, end user and grant, and calls in the same run share a trace id. your case spans two sessions though, so the thing linking them is the slack message itself, not a trace
your noise point is honestly why we haven't done taint tracking yet, the "user typed the address but it was also in tool output" case is exactly the hard bit. it's a really interesting scenario though, we'll look into whether it makes sense for us to support this kind of thing natively.
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.
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.
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.
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.
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.
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.
- every outbound request goes through our proxy. the agent never holds the downstream credential so there's no path around it, and policy is evaluated deterministically there, not by the model. every call gets an audit row, denials included, with the agent, the end user it was acting for, the delegation chain, the grant, the operation, and the policy decision plus which rule produced it. so "user X did Y on Z at T and here's why it was allowed" is answerable after the fact
- User to resource mapping, honest answer is it depends on the credential. Where the provider supports it we push per-user oauth, so each end user connects their own account and the provider's own ownership checks apply. that's the cleanest least privilege - With a shared key we can't know who owns invoice 123 unless something tells us. what we do have is rules on the operation and its params (methods, paths, ids, recipients, amounts), so you can pin a user or agent to specific resources. but we don't keep a general ownership graph of your customers' data, that mapping still lives with you or the provider
On the rest: agents can only ever get a subset of the user's permissions (delegation narrows, never widens), money moving and destructive ops can require human approval on the exact frozen request, and our ai review can only escalate to a human, never allow something the rules didn't