← All AI Engineer talks

AI Engineer World's Fair 2026

You Didn't Ship a Bug. You Just Wrote It for a Human.

Read the talk

You Didn't Ship a Bug. You Just Wrote It for a Human.

A harmless timestamp update reveals a deeper architectural problem: agents need their own identities, authority tied to specific users and tasks, and deterministic controls on every action.

From a talk by Ravi Madabhushi

Before you start: Familiarity with API credentials, OAuth scopes and agent tool calls will help you follow the authorization examples.

The timestamp assumption that broke

Scalekit's latency was spiking every 15 minutes, Ravi Madabhushi reports. The pattern was regular enough to investigate, even though it was not causing a harmful incident.

A red line chart shows four recurring spikes above a dashed alert threshold, beneath the heading “Every fifteen minutes, the database strained.”
Every fifteen minutes, the database strained.

The cause was an ordinary piece of identity infrastructure: a per-user timestamp recording when someone was last seen or last active. Updating it helped distinguish active users from inactive ones. But the implementation assumed a human pace of activity. As agents began hitting the APIs over roughly the preceding year, that assumption stopped holding. Ravi reports that agent traffic drove last-seen timestamp updates 60 times faster than human traffic, putting unnecessary pressure on database writes.

The fix was small: batch updates at second-level granularity instead of writing on every action. The more consequential question came afterward. If a harmless activity timestamp encoded the wrong assumptions about agents, what assumptions were hiding in authentication and authorization? An API can behave exactly as designed and still be designed for the wrong kind of actor.

0:200:33
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:20 · section reference included

Why agents inherit excessive permissions

Ravi Madabhushi, a Scalekit co-founder, approaches this problem through identity infrastructure. He reports a decade working in identity and authorization, including building a Freshworks identity platform used by millions of daily users. Those systems primarily served humans—or machine clients whose behavior humans had written into programs.

The newer pattern is an agent gathering context from Salesforce, Databricks, HubSpot or Notion to carry out a job. Across the customer agents his team encounters, Ravi sees permissions and scopes that exceed those jobs. His diagnosis is not careless development: connecting an agent to useful data has become a default workflow, while the available permission primitives often cannot express the narrow authority the job actually requires.

1:562:10
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

1:56 · section reference included

The two inherited identity models

Existing applications commonly offer two places to put a caller's identity:

ModelCredential or access pathIdentity attached to actions
Human userWeb or mobile session; personal script with an API keyThe user
Service accountCredentials issued to a machine accountThe machine account

In the first model, a script effectively carries the user's identity into the application. In the second, the machine receives an identity and permissions of its own. Ravi names SPIFFE and OAuth as existing infrastructure in this space. They address different layers: SPIFFE supplies workload identity and authentication, while OAuth provides an authorization framework; workload identity alone does not enforce application permissions.

The shared assumption in Ravi's account is that whoever authenticates is also the actor. A password establishes continuity with a registered human identity, and subsequent actions attach to that identity. API keys, web session tokens and service-account credentials similarly connect requests to a known caller. He describes the inherited permission model as authority assigned at registration and reused on later actions. That is the architectural pattern under examination, rather than a requirement that all authorization systems keep permissions fixed forever.

3:193:37
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

3:19 · section reference included

Code inspection supplied part of the safety argument

Broad permissions were easier to justify when a human-written program constrained how those permissions would be used. An API key might collapse actor and principal into the same identity; delegated access could instead limit a program to permissions the user had consented to. In either case, developers could inspect the code to understand the intended actions.

Ravi calls this staying in one's lane: a deterministic program follows the behavior its developer encoded. Determinism is not itself a security guarantee—bugs and unintended behavior remain possible—but inspectable control flow supplies a reviewable account of how authority will be exercised.

Two numbered cards state “It acts as itself: principal = actor” and “It stays in its lane: deterministic,” with password, API Key, session, and Service account labels.
Two assumptions behind broad access: principal equals actor, and programs stay deterministic.

He uses Google's review process for applications requesting sensitive access as an example of that reviewable boundary. The precise distinction matters: Google's sensitive-scope verification is not identical to a third-party security assessment, which its guidance associates with certain restricted-scope uses. The relevant architectural point is that an application can be reviewed for how it handles the access it requests.

5:095:26
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:09 · section reference included

Separate the principal from the actor

An agent reading someone's Gmail or accessing their Salesforce records introduces two parties that need to remain distinguishable. The principal is the user on whose behalf the work happens; the actor is the agent performing it. Ravi reports that incomplete OAuth support in the systems his team encounters often obscures this relationship. If the agent simply uses the user's credentials, the application may not be able to distinguish delegated activity from the user's own actions.

The second break is behavioral. An agent's action sequence can change on the next run, so yesterday's successful execution does not establish what it will do tomorrow. The identity choice then becomes consequential: give the agent a distinct identity and let it act on behalf of a user, or let it act as that user. Ravi points to an OAuth client_id for identifying the client; technically, that identifier names a client registration, is not sufficient authentication by itself, and does not establish a separate identity for every execution.

Acting on behalf of someone preserves a relationship that impersonation hides. The same agent may work for several users, but its permissions must depend on which user authorized the current work. OAuth provides the foundation through user consent to specific scopes: authority to perform certain operations, rather than unrestricted authority inherited from the user.

6:326:51
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

6:32 · section reference included

The tool surface must reflect authorization

That user-specific authority often disappears when an agent receives its tool context. Ravi reports that most MCP servers his team has worked with do not limit that context according to the user who authorized the agent. They expose all tools the user can access—or even every tool the application supports—and leave the agent to choose. This describes the deployments his team encountered, not a requirement of MCP.

The resulting failure can happen before an unauthorized operation executes: the agent sees the wrong tool, selects it and attempts the wrong action. A runtime authorization check may block the call, but the agent still received the same tool surface regardless of whom it represented. Tool visibility and execution permission are separate boundaries. Narrow discovery to the authorized task, while retaining enforcement at invocation; hiding a tool is not a substitute for checking access when it is called.

8:268:43
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:26 · section reference included

Make authority narrow, temporary and enforceable

The first requirement is to keep the agent's own identity bound to the principal it represents. The second is to express authority more precisely than a broad operation-level scope. Permission to send email on a user's behalf leaves several important questions unanswered:

  • Time: During which hours may the agent act?
  • Read access: From which senders may it read messages?
  • Write access: To which recipients may it send messages?

These constraints describe the job more accurately than a single yes-or-no permission to use email.

Authority should also last only for the period of work and cover only the tools required by that work. A policy check can remain deterministic even when the agent's choice of action is probabilistic. For example, an application could evaluate a proposed email against a trusted grant before permitting delivery:

typescript

type EmailGrant = {
  actorId: string;
  principalId: string;
  tool: "send_email";
  validFrom: number;
  expiresAt: number;
  recipients: readonly string[];
};

type ProposedEmail = {
  actorId: string;
  principalId: string;
  tool: "send_email";
  to: string;
};

function permitsEmail(
  grant: EmailGrant,
  proposed: ProposedEmail,
  now: number,
): boolean {
  return (
    proposed.actorId === grant.actorId &&
    proposed.principalId === grant.principalId &&
    proposed.tool === grant.tool &&
    now >= grant.validFrom &&
    now < grant.expiresAt &&
    grant.recipients.includes(proposed.to)
  );
}

Here the grant comes from the authorization system, and the actor and principal must come from validated request context, not identities asserted by the model. The function decides whether a proposed operation is permitted; it does not send the email.

This moves the safety boundary away from confidence in the agent's future behavior and into enforced policy. Ravi's prescription is attribute-level, context-level and principal-level scoping, with least privilege by default. When a task genuinely needs more authority, the agent should request just-in-time authorization for elevated scopes rather than start with every permission it might eventually use.

Agent and user boxes are joined by “on behalf of” and “BOUND. SCOPED. AUDITABLE.” Four labels specify enforcement every call, user scope, task scope, and least privilege by default.
Bind the agent to the user it acts on behalf of, with scoped access and least privilege.
9:109:21
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

9:10 · section reference included

The actors are already agents

These controls address an existing operational problem. Ravi cites destructive agent behavior, including production database deletion, as a reason to build deterministic guardrails now. He does not identify a particular incident or its failure mechanism.

He also describes Ref.tools, a Scalekit customer whose product supplies context to coding agents, as having no humans as actors in this workflow. According to Ravi, the customer built OAuth scoping into that agent-facing product. The example shifts the design starting point: an API may primarily serve agents, so its identity and permission model cannot depend on treating agent access as an occasional extension of a human session.

11:0511:13
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

11:05 · section reference included

Know who acted, for whom and under what authority

Fine-grained control needs an equally precise record of its use. For every action, the system should be able to answer:

  • Actor: Which agent took the action?
  • Principal: On whose behalf did it act?
  • Authorizer: Who approved the authority?
  • Grant: What permissions were approved, and when?
  • Duration: How long was that authorization valid?

These are the facts needed to connect an operation to the permission that allowed it.

Visibility alone is insufficient if the system cannot deterministically prevent actions outside that authority. As Ravi puts it, “praying is not a strategy.” The architecture must both explain what an agent can do and control what it is allowed to do.

A slide asks whether you know and can control what your agent can do, with smaller text calling for deterministic control and stating “PRAYING is NOT a STRATEGY.”
Do you know what your agent can do right now, and can you control it?

OAuth is a useful starting point for that architecture. The remaining work is to enforce finer access controls around the particular user, task and operating context, while preserving the agent's own identity. An agent should act as itself, on behalf of a specific user, within authority the application can verify—not authority inferred from the hope that it will choose the right action.

11:3711:50
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

11:37 · section reference included

Resources

From the talk

Read the complete timestamped transcript
  1. 0:00

    Hi, thank you so much for tuning in. I'm Ravi. I'm one of the co-founders of Scalekit. Today, I'm going to talk about how you need to think architecturally from the ground up about building your application's APIs, your MCP servers for agents, and how the human-focused architecture doesn't scale well for agents.

  2. 0:20

    So a while back, we were looking at our performance and latency numbers, and one thing that kind of jumped out at us was how our latency was spiking every 15 minutes in a rhythmic manner.

  3. 0:33

    Nothing harmful, but just a curious thing for us to analyze. What we noticed was very interesting. So in our identity and authentication infrastructure platform, we have this little timestamp that we mark for every user to say, "Hey, when was the user last seen?

  4. 0:47

    Or when was the user last active or last acted in our system?" So that we can predictively say, "Hey, this user is an active user. This user is not so active."

  5. 0:57

    But one thing that we realized was the system was predominantly built for humans. But when agents started hitting our APIs in the last 12 months or so, we realized that this last seen update is happening 60 times faster than what it would, and that is creating unnecessary pressure in our DB write system.

  6. 1:19

    So of course, it's a harmless thing. We were able to fix it very easily. We would just batch the update at a second level and not at every single time we had to update it.

  7. 1:30

    That kind of took us down a rabbit hole. So the assumption that broke was how often would our system have to update this timestamp on every row, and that's okay.

  8. 1:39

    It's just about speed, it's about latency, et cetera. But what I was worried about is, hey, what if some of our assumptions that we made about authentication and authorization need to be revised and rethought completely when it comes to agents because we would have designed earlier for humans as actors in mind.

  9. 1:56

    Now, just to give you a context, I worked on identity and authentication authorization for the last 10 years, building an identity platform at Freshworks, which is being used by millions of daily users, hundreds and thousands of customers all over the world.

  10. 2:10

    But this is predominantly human users, right? Or at best, APIs. But the way I think about it is APIs are also accessed by machines that are written by humans.

  11. 2:22

    That's not too bad, right? But what I realized is the fundamental picture has changed drastically in the last three, four years or so.

  12. 2:32

    We have a unique ringside view to see how developers nowadays are building agents and how they're giving context to these agents with data from third-party applications like Salesforce or, or Databricks or HubSpot or Notion.

  13. 2:46

    What we have realized is most of the agents our customers are building have way too permissions and scopes than the agent's responsibility or the agent's job is. Again, it's not because the developers who are building the agents are careless.

  14. 3:06

    But somehow this became a default pattern of giving the agents what they need access to, and the existing primitives that we have don't let us give extremely fine-grained permissions to the agents.

  15. 3:19

    Now, I'll tell you how we ended up here, right? We predominantly have two slots, and neither of the slots was built for agents in mind. There's a human who's accessing the application, either a web application or a mobile application or their own little script that they wrote, and they give it their API key so that their program

  16. 3:37

    can access data from the application. This is all... The fundamental principle here is it's the same user who is authenticating, and it's the same user who is acting, right?

  17. 3:48

    And the second slot is the traditional service account scenario or end-to-end account scenario where you create a service account, you give it certain permissions, and then say, "This machine has its own identity."

  18. 3:59

    That's where the likes of SPIFFE and, and OAuth and all of that came into picture. But you would give them certain credentials and say, "Hey, now this machine has access to whatever data that it needs at any single point of time."

  19. 4:12

    And this is the existing pattern, right? So the fundamental philosophy that we have always maintained is whoever is authenticating is the one that is acting. Every action the program or the human takes is based on fixed set of permissions that actor was granted at some time.

  20. 4:30

    If you take traditional authentication mechanisms for humans, including password, you just say, "Hey, if an identity has the same password that it was set at the time of registration, if they come back and if they present the same password again," then you say, "Okay, this is how I validate the identity.

  21. 4:45

    This is how I authenticate the human." And every action subsequently is tied to that human identity. Again, the same is the case with API key or the same is the case with web session tokens or even the same case for service account.

  22. 4:59

    You define the permissions at the time of registration, and then every single time it acts based on the registration time, permissions, and scopes.

  23. 5:09

    Now, this is okay all this while because for decades the service account and OAuth principle even is working fine even though there are their own problems, but it is still working fine because these machines are

  24. 5:26

    using a program in a deterministic way, by the way the human developer wrote that program. So there is absolute guarantees about what the program could or the program won't do, but it is still intentional based on what the human wrote, right?

  25. 5:44

    In this particular case, again, if it is using API keys, then the actor and the principal is the same. Then there is some sort of a delegated permission for the program to act based on what consent the user has granted.

  26. 5:57

    But the second one is the most important part, which is it's a deterministic program, and it always stays in its own lane. It can never do what it was not programmed to do, and- You could inspect the code to say, "Okay, is the program doing what it is supposed to do?"

  27. 6:13

    Even if you apply for a Google developer account and then ask for client ID, and you need to access sensitive scopes, you have to go through a security review.

  28. 6:19

    So what they're doing is they're looking at your code base to say, "Are you doing enough checks, the appropriate practices in place?" So these programs are deterministic. These programs behave the exact same way a developer programmed them to work.

  29. 6:32

    But agents fundamentally break this assumption, right? First of all, in the case of agents, the principle is not the same as an actor. You need to give delegated access so that the agent can act on behalf of the user, agent can access the user's Gmail, agent can access the user's Salesforce data, whatever the case may be.

  30. 6:51

    But again, unfortunately, not a lot of systems, even today, support OAuth. So here again, there is no on-behalf-of principle that is working, so you don't even know if there is a program that is acting on behalf of the user or the user acting by themselves, right?

  31. 7:08

    That's a fundamental problem. The second problem is even more dangerous, which is

  32. 7:13

    right now the program is not written by a human. There is no determinism baked in to say what the agent will do or won't do. Just because an agent does certain things today, you can't be 100% certain that the agent can't do the same or the exact same thing tomorrow, day after, or even if it's the next

  33. 7:31

    immediate run, right? Because of this non-deterministic nature of the agent, we usually pick one of the two lanes, right? You give a specific identity to the agent, which is what we call as client ID in the context of OAuth, and then say, "You act on behalf of this particular user," or we go back to the agent acts

  34. 7:54

    as the user, which is even worse. The fundamental reason why I'm harping on the same thing is because when an agent is acting on behalf of user one versus user two or user three, the agent needs specific permissions based on the user's context.

  35. 8:12

    Now, the OAuth solved this perfectly fine by saying, "Hey, the user will grant specific scopes or permissions to the agent so that the agent is acting on behalf of the user.

  36. 8:26

    It can't do everything, but the agent will only do certain things." Now, in the kind of world that we're living in, most of the MCP servers that we've worked with don't actually limit the tool context access to the agent based on which user authorized the agent.

  37. 8:43

    They typically surface all the tools that the user has access to or all the tools that the application can even support and then let the agent determine what they can or cannot do.

  38. 8:57

    And now the agent ends up picking the wrong tool, doing the wrong things. Maybe there is some runtime check in the application that prevents some of these things, but the agent is still seeing the same surface regardless whom it is acting for.

  39. 9:10

    Now, two things that we need to solve for. One is the actor, in this case an agent, has to be bound to the principle at all times, and the agent should have its own identity.

  40. 9:21

    Agent should have extremely fine-grained credentials, not the OAuth scopes that we are seeing today. If you inspect the scopes for some of these applications, like even very popular applications like Gmail, it will say, "Can this client send emails on your behalf?"

  41. 9:36

    There is no extremely fine-grained scoping to say, "Can this agent act at this hour? Can this agent read emails only from these senders? Can this agent send emails to only these recipients?"

  42. 9:48

    The reason why that is important is because, again, we spoke about this earlier, in the context of non-deterministic agent workflows, it's extremely important that the agent should have permissions for limited amount of time that they're operating in, number one.

  43. 10:04

    Every agent has a goal, every agent has a job, so you should be able to deterministically say that this agent should have access only to those tools or only to those jobs it has access to.

  44. 10:15

    So gone are the days when the broad-scoped OAuth scopes that we defined is okay because in that case, developer was writing a deterministic application, and you can review the code to make sure that he's not doing anything sinister.

  45. 10:30

    But in the case of agents, it's extremely non-deterministic. It is probabilistic. Agents are bound to do things, whatever they can get a hold of. So in the context of when you are giving access to the agents, you should be in a position to give extremely fine-grained scopes.

  46. 10:46

    It should be at an attribute-level scoping, it should be context-level scoping, it should be principle-level scoping. So all of that is extremely important. Again, I think everyone agrees that agents should be least privileged by default, and they should be able to ask for just-in-time authorization if they want elevated scopes.

  47. 11:05

    Now, the reason why we are talking about this is because it's not some futuristic thing. It is happening today. We have seen enough incidents where agents end up doing rogue things.

  48. 11:13

    They end up deleting production databases and stuff like that. So how do you put deterministic guardrails in place is an important problem to be solved right now. Again, one of our customers, Ref.tools, they don't even have humans as actors.

  49. 11:27

    Their predominant product is about how to give context to coding agents so that they can do their job effectively. So they built the entire OAuth scoping, how do you do things the right way and things like that.

  50. 11:37

    So the reason why I give this example is not to say that this is a warning shot, but this is a problem of today and not for tomorrow. Before I go, you have to have absolute visibility into what your agent can do.

  51. 11:50

    Every action that's taken in your system, who took it on behalf of whom, and who authorized it? When was the authorization given? What authorization was given? How long is it given for?

  52. 12:03

    If you don't have visibility into all these actions at every single time, and if you can't deterministically control what your agent can or cannot do, then you're just praying that agent doesn't end up doing what it's not supposed to do.

  53. 12:16

    And praying is not a strategy, as we all know. One last thing to take away. If you architected so far with humans and APIs in mind, you need to start rethinking about how you need to give deterministic guardrails and deterministic authorization controls to the agent.

  54. 12:34

    And OAuth is a good place to start, but you need something beyond OAuth to make sure that the agents have extremely fine-grained access controls and agents are always acting by themselves on behalf of certain users.

  55. 12:46

    Thank you so much for your time.