# Function context

> The identities, platform coordinates, and request data the runtime passes to every JavaScript function handler.

Every handler receives a context object as its second argument. It carries who called the function, the function's own platform identity, and where to send outbound platform calls — so none of that has to be passed in as input.

```typescript
handler: async (input, ctx) => {
  ctx.user?.accessToken     // the caller's OAuth token
  ctx.user?.sub             // the caller's user id
  ctx.robot?.accessToken    // the function's own platform token
  ctx.robot?.key            // the serverless robot key
  ctx.platform?.baseUrl     // e.g. "https://cloud.uipath.com"
  ctx.platform?.orgId       // organization id
  ctx.platform?.tenantId    // tenant id
  ctx.platform?.folderKey   // folder of the invocation, if any
  ctx.params                // path parameters, as strings
  ctx.headers               // request headers, lowercase keys
}
```

## Two identities

A function is handed two identities per invocation, and the choice between them is a security decision.

| | `ctx.user` | `ctx.robot` |
|---|---|---|
| Whose it is | The caller who invoked the function | The function's own platform identity |
| Permissions that apply | The caller's own | The function's service account |
| Use it for | Acting on behalf of the signed-in user | Reading resources the caller must not reach directly |

`ctx.user.accessToken` applies when the caller should only see what their own permissions allow. `ctx.robot.accessToken` applies when the function must reach something the caller cannot — a credential in a restricted folder, for example. See [Accessing platform services](javascript-platform-services.md).

:::note
`ctx.robot` is the more privileged identity. A handler that reads whatever resource name arrives in the request is acting as a deputy for the caller's request with the function's own privileges. Fetching must be constrained to a fixed set in code.
:::

## Platform coordinates

`ctx.platform` supplies `baseUrl`, `orgId` and `tenantId` for outbound platform calls. These come from the runtime, never from the caller, so a request cannot redirect where the function sends its traffic, and they must never be accepted as input fields.

It is all-or-nothing: `ctx.platform` is `null` unless all three are available. `folderKey` can be `null` on its own, for a folderless invocation.

## What is available where

| | HTTP trigger | Job | Local `serve` |
|---|---|---|---|
| `ctx.user` | The caller's identity | No caller identity | Present when the request carries a bearer token |
| `ctx.robot` | Yes | Yes | `null` |
| `ctx.platform` | Yes | Yes | Only with `UIPATH_BASE_URL`, `UIPATH_ORG_ID` and `UIPATH_TENANT_ID` set |
| `ctx.params`, `ctx.headers` | Yes | Empty — there is no HTTP request | Yes |

Because `ctx.robot` is `null` locally, code that needs a platform token should fall back to an environment variable for local development:

```typescript
const token = ctx.robot?.accessToken || process.env["UIPATH_ACCESS_TOKEN"] || "";
```

## Next steps

- [Accessing platform services](javascript-platform-services.md)
- [Testing and debugging](javascript-testing-and-debugging.md)
- [Context reference](https://uipath.github.io/uipath-typescript/js-functions/api/function-context/) — the full type and every field.
