# The ctx object

> Field-by-field reference for the ctx object Helix functions receive, plus getContext() for shared code and availability by function type.

Every Helix function execution receives a `ctx` object as its handler argument. It carries the project-scoped key-value store, outbound HTTP including authenticated calls, AI model calls, logging, the validated request input, response helpers, execution metadata, and caller identity. Shared code outside the handler can reach the same object with `getContext()`.

## Surface

| Field | Type | Reference |
|---|---|---|
| `log` | `ContextLogger` | [ctx.log](/documentation/reference/context/log/) |
| `http` | `KyInstance` | [ctx.http](/documentation/reference/context/http/) |
| `auth(alias)` | `Promise<Record<string, string>>` | [ctx.auth()](/documentation/reference/context/http/) |
| `kv()` | `KeyValueStore` | [ctx.kv()](/documentation/reference/context/kv/) |
| `ai(alias)` | `HelixAIProvider` | [ctx.ai()](/documentation/reference/context/ai/) |
| `callFunctionAsync(path, input?)` | `Promise<void>` | [ctx.callFunctionAsync()](/documentation/reference/context/async/) |
| `input` | Validated merged input | [Request and response](/documentation/reference/context/request/) |
| `method`, `headers`, `path` | `string`, `Headers`, `string` | [Request and response](/documentation/reference/context/request/) |
| `request` | Raw request accessor | [Request and response](/documentation/reference/context/request/) |
| `status(code)` | `void` | [Request and response](/documentation/reference/context/request/) |
| `error(status, message)` | `HttpError` (throw it) | [Request and response](/documentation/reference/context/request/) |
| `trigger` | Trigger data by function type | [Request and response](/documentation/reference/context/request/) |
| `identity` | `IdentityContext \| null` | [ctx.identity](/documentation/reference/context/identity/) |
| `state` | `Record<string, any>` | [Request and response](/documentation/reference/context/request/) |
| `executionId` | `string` | This page, below |
| `parentExecutionId` | `string \| null` | [ctx.callFunctionAsync()](/documentation/reference/context/async/) |
| `userId` | `string \| null` | This page, below |
| `projectId` | `string \| null` | This page, below |
| `workspaceId` | `string \| null` | This page, below |
| `organizationId` | `string \| null` | This page, below |

`kv()` takes no argument and is always project-scoped. `identity` ships, but only `user.id` populates reliably right now, so treat `email`, `name`, `groups`, `roles`, and `org` as incomplete. HTTP requests and cron schedules ([`defineSchedule`](/documentation/guides/scheduled-functions/)) are the triggers a function can have. The shipped data service is the project-scoped [key-value store](/documentation/guides/key-value-store/).

## Execution metadata

Five fields identify where an execution runs and who invoked it. Each is `null` when unknown, for example in an unprovisioned local project.

| Field | Meaning |
|---|---|
| `executionId` | UUID per invocation, used for correlation and tracing |
| `userId` | The invoking user, mirrors `identity.user.id` |
| `projectId` | The project this deployment belongs to |
| `workspaceId` | The workspace this deployment belongs to |
| `organizationId` | The organization this deployment belongs to |

| Field | Production | Local (`helix dev`) |
|---|---|---|
| `executionId` | Set per invocation | Set per request |
| `userId` | The signed-in caller, when known | From the local session, or null |
| `projectId` | The deployed project | `projectId` in `helix.config.ts` (null if unprovisioned) |
| `workspaceId` | The deployment's workspace | `workspaceId` in `helix.config.ts` (null if unset) |
| `organizationId` | The deployment's organization | From local identity when available, otherwise null |

`projectId`, `workspaceId`, and `organizationId` identify the deployment; `userId` identifies the caller. See [ctx.identity](/documentation/reference/context/identity/).

## getContext()

Handlers receive `ctx` as a parameter. Shared utilities deeper in the call chain can access the same context without threading it through every call:

```typescript
import { getContext } from '@trayai/helix-sdk';

function getContext(): FunctionContext
```

The context is stored in Node.js `AsyncLocalStorage`, scoped per execution, so concurrent requests never bleed into each other. Calling `getContext()` outside a function execution throws: "getContext() called outside of a Helix function execution."

```typescript
// functions/_shared/salesforce.ts
import { getContext } from '@trayai/helix-sdk';

const AUTH = 'salesforce_prod';
const API = 'https://acme.my.salesforce.com/services/data/v59.0';

export async function query<T = any>(soql: string): Promise<T[]> {
  const { http } = getContext(); // no ctx parameter needed
  const res = await http
    .authed(AUTH)
    .get(`${API}/query`, { query: { q: soql } });
  return (res.body as { records: T[] }).records;
}
```

| Situation | Use |
|---|---|
| Function handler (top level) | The `ctx` parameter |
| Shared utilities in `_shared/` | `getContext()` |
| Unit testing shared code | `runWithContext()` from the testing module |
| Code outside a function execution | Neither works; the error message says so |

## runWithContext() for tests

To unit test shared code that calls `getContext()`, wrap the call in a mock context:

```typescript
// tests/shared/salesforce.test.ts
import { runWithContext } from '@trayai/helix-sdk/testing';
import { query } from '../functions/_shared/salesforce';

test('query returns contacts', async () => {
  const result = await runWithContext(
    { http: mockKyInstance, kv: mockKvStore },
    () => query('SELECT Id FROM Contact'),
  );

  expect(result).toEqual([{ Id: '003xx...' }]);
});
```

## Availability by function type

Not every field exists on every function type. Accessing an unavailable field throws a clear runtime error naming the function types that support it.

| Context field | `defineFunction` | `defineSchedule` |
|---|:---:|:---:|
| `log` | ✓ | ✓ |
| `http` | ✓ | ✓ |
| `auth()` | ✓ | ✓ |
| `kv()` | ✓ | ✓ |
| `ai(alias)` | ✓ | ✓ |
| `callFunctionAsync()` | ✓ | ✓ |
| `parentExecutionId` | ✓ | ✗ |
| `input` | ✓ | ✗ |
| `method` | ✓ | ✗ |
| `headers` | ✓ | ✗ |
| `request` | ✓ | ✗ |
| `status()` | ✓ | ✗ |
| `error()` | ✓ | ✓ |
| `trigger.scheduledAt` | ✗ | ✓ |
| `identity` | ✓ | ✗ |
| `state` | ✓ | ✗ |

For how each function type is declared and routed, see [the functions and routing guide](/documentation/guides/functions-and-routing/).

---

Canonical: https://helix.tray.ai/documentation/reference/context/
Any link on this page is available as markdown by appending .md to its URL.
Full corpus: https://helix.tray.ai/documentation/llms-full.txt