diff --git a/agents/build/configuration.mdx b/agents/build/configuration.mdx
index 4c869a6..0cfa7a2 100644
--- a/agents/build/configuration.mdx
+++ b/agents/build/configuration.mdx
@@ -93,6 +93,14 @@ Turn it off if callers should be able to interrupt the agent within those 3 seco
`conversation.timezone` is the default IANA timezone (like `Asia/Tokyo`) the agent uses for dates and times in conversation. Leave it empty for **automatic**: each session follows the caller's device or phone number, falling back to UTC. Set one when your agent serves a single region regardless of who calls. A per-session `timezone` on the [session request](/agents/build/time-timezone) overrides this. See [Time & timezone](/agents/build/time-timezone) for the full resolution order.
+## Context
+
+The `context` section holds the facts the platform tells your agent on its own, one switch each. Guardrails constrain what the agent does, context switches add to what it knows.
+
+### Current date and time
+
+`context.current_time` (default `false`) tells the agent today's date when a session starts and the current time before every reply, in the agent's [timezone](#timezone). In the Builder this is the **Current date & time** toggle under the time zone. Turn it on for scheduling, reminders, or any prompt that says "tomorrow" or "next Tuesday". Leave it off when the prompt states its own date, for example a role-play set on a fictional day. Agents created before the switch existed have it on, which was their behavior. A session request's `context.current_time` overrides the agent's setting in either direction. See [Time & timezone](/agents/build/time-timezone).
+
## Autosave and publishing
There is no Save button. Each change is written to the agent's draft moments after you stop editing, and the **Saving… / Saved** indicator at the bottom-left of the page shows the current state. If a save fails, the Builder tells you and keeps your pending edits so nothing is lost.
@@ -139,6 +147,9 @@ curl --request GET "https://api.fish.audio/v1/agent/agents/$AGENT_ID/config" \
"echo_guard": null,
"speculative_response": true,
"timezone": ""
+ },
+ "context": {
+ "current_time": false
}
}
```
@@ -169,6 +180,7 @@ The response includes the draft's new `config_hash`. Values outside the document
| `voice` | Voice profile, text-to-speech model, speaking language, and expressive mode | [Voice & language](/agents/build/voice-language) |
| `asr` | Speech recognition model, multilingual recognition, strict language, and recognition keyterms | [Voice & language](/agents/build/voice-language#speech-recognition-model) |
| `conversation` | Call duration, turn-taking, interruption behavior, timezone, and storage | This page; storage in [Conversation history](/agents/monitor/conversation-history#what-gets-stored) |
+| `context` | Facts the platform tells the agent on its own, currently the current date and time | This page |
| `tools` | Attached webhook tools and system tool switches | [Tools](/agents/build/tools) |
| `knowledge_base` | Attached knowledge sources | [Knowledge base](/agents/build/knowledge-base) |
| `analysis` | Post-call summary, data fields, and success criteria | [Post-call analysis](/agents/monitor/post-call-analysis) |
diff --git a/agents/build/dynamic-variables.mdx b/agents/build/dynamic-variables.mdx
index 5b18844..0b31f69 100644
--- a/agents/build/dynamic-variables.mdx
+++ b/agents/build/dynamic-variables.mdx
@@ -148,7 +148,7 @@ The platform fills a handful of `{{system.*}}` placeholders itself, on every ses
|---|---|---|
| `system.channel` | `phone_inbound`, `phone_outbound`, or `web_voice` | Web SDK, API, preview, and Single Turn and Tool test sessions are `web_voice`. A Simulation test uses its [channel](/agents/test/agent-tests#channel). |
| `system.timezone` | The session's resolved IANA timezone, for example `Asia/Tokyo` | `UTC` when nothing resolves. Always equals the session's `timezone` field; see [which timezone a session uses](/agents/build/time-timezone#which-timezone-a-session-uses). |
-| `system.today` | Today's date in that timezone, ISO 8601 `YYYY-MM-DD` | The calendar date at session creation. There is no `system.now`; see [World context](#world-context). |
+| `system.today` | Today's date in that timezone, ISO 8601 `YYYY-MM-DD` | The calendar date at session creation. There is no `system.now`; see [Current date and time](#current-date-and-time). |
| `system.language` | The session language code, one of the [52 supported languages](/agents/build/voice-language#speaking-language) | The `language` [override](/agents/deploy/authenticated-sessions#overrides) when the request carries one, otherwise the agent's [speaking language](/agents/build/voice-language#speaking-language). |
| `system.caller_number` | The human party's number, E.164 | Inbound: the caller (empty if withheld or not a valid E.164 number). Outbound: the number you dialed. Empty on non-phone sessions. |
| `system.caller_number_spoken` | The same number written for speech, for example `+1; 4 1 5; 5 5 5; 0 1 2 3` | Use it wherever the agent should say the number out loud; see [Reading a number out loud](#reading-a-number-out-loud). Empty whenever `system.caller_number` is empty. |
@@ -183,7 +183,7 @@ On a web session the same prompt renders `The caller's number is "".`, and the a
### Date and timezone
-`system.today` is always ISO formatted, whatever the session language: in the system prompt the model reads it and speaks it in the session's language, while a fixed first message containing `{{system.today}}` is spoken verbatim as `2026-08-21`. A session that runs past midnight keeps its opening date. Template it, and `system.timezone`, when a request needs them explicitly, for example a webhook tool's query string; for the agent's own sense of time no variable is needed, see [World context](#world-context).
+`system.today` is always ISO formatted, whatever the session language: in the system prompt the model reads it and speaks it in the session's language, while a fixed first message containing `{{system.today}}` is spoken verbatim as `2026-08-21`. A session that runs past midnight keeps its opening date. Template it, and `system.timezone`, when a request needs them explicitly, for example a webhook tool's query string; for the agent's own sense of time, turn on the agent's `context.current_time` switch instead of templating, see [Current date and time](#current-date-and-time).
### In webhook tools
@@ -197,11 +197,11 @@ https://crm.example.com/availability?phone={{system.caller_number}}&from={{syste
A reference to a system variable that does not exist (`{{system.foo}}`) is rejected with `422` when you save the configuration or the tool, and when you send it in session overrides. The error lists the available names.
-## World context
+## Current date and time
-The agent knows the current date and time without any variable. The platform states the date and the session's timezone at the start of every session and refreshes the time on every turn, so "tomorrow morning" or "next Tuesday" resolve correctly even in a long conversation. You don't need a custom `{{today}}` or `{{now}}`, and there is no `system.now`: variables render once, when the session is created, so a templated time would be stale from the first reply onward. When you want the date or timezone as text in a template, for example in a webhook tool URL, use the [`system.today` and `system.timezone`](#system-variables) system variables.
+With the agent's `context.current_time` switch on, the agent knows the current date and time without any variable: the platform states the date and the session's timezone at the start of every session and refreshes the time on every turn, so "tomorrow morning" or "next Tuesday" resolve correctly even in a long conversation. You don't need a custom `{{today}}` or `{{now}}`, and there is no `system.now`: variables render once, when the session is created, so a templated time would be stale from the first reply onward. When you want the date or timezone as text in a template, for example in a webhook tool URL, use the [`system.today` and `system.timezone`](#system-variables) system variables, which work whether the switch is on or off.
-See [Time & timezone](/agents/build/time-timezone) for how the timezone is resolved and how to turn the injection off for a session (`world_context: false`).
+See [Time & timezone](/agents/build/time-timezone) for how the timezone is resolved and how the switch works per agent and per session.
## Going further
diff --git a/agents/build/time-timezone.mdx b/agents/build/time-timezone.mdx
index c1f0a95..2b04b03 100644
--- a/agents/build/time-timezone.mdx
+++ b/agents/build/time-timezone.mdx
@@ -1,10 +1,10 @@
---
title: "Time & Timezone"
-description: "Your agent knows the current date and time by default: how the timezone is chosen and how to opt out"
+description: "Let your agent know the current date and time: the switch, how the timezone is chosen, and per-session overrides"
icon: "clock"
---
-Agents are time-aware out of the box: every session knows today's date and the current time in the session's timezone. You don't reference a variable or add anything to your prompt: "tomorrow morning" and "next Tuesday" ground correctly from the first turn, on every channel (voice, text, and phone).
+An agent can know today's date and the current time in the session's timezone without you adding anything to the prompt. The switch is `context.current_time` in the agent's [configuration](/agents/build/configuration#current-date-and-time), the **Current date & time** toggle under the time zone in the Builder. It is off for new agents and on for agents created before the switch existed. With it on, "tomorrow morning" and "next Tuesday" ground correctly from the first turn, on every channel (voice, text, and phone).
The default timezone is **UTC**. Change it for the agent in its
@@ -15,7 +15,7 @@ Agents are time-aware out of the box: every session knows today's date and the c
## What the agent knows
-Fish Audio injects two pieces of world context server-side:
+With the switch on, Fish Audio injects two lines server-side:
| When | What | Example |
| ------------------ | ---------------------------- | ------------------------------------------------------------------ |
@@ -29,7 +29,7 @@ The time is refreshed on every turn, so it stays accurate through long conversat
system prompt's character limit.
-Both facts also exist as [system variables](/agents/build/dynamic-variables#system-variables) for the cases where you want to template them yourself, for example into a webhook tool's URL: `{{system.today}}` is the date at session creation as ISO `YYYY-MM-DD`, and `{{system.timezone}}` is the resolved IANA name (`UTC` when nothing resolves). There is no `{{system.now}}`: variables render once, when the session is created, so a templated clock would freeze at the opening. The per-turn time above is the one to rely on.
+Both facts also exist as [system variables](/agents/build/dynamic-variables#system-variables), available whether the switch is on or off, for the cases where you want to template them yourself, for example into a webhook tool's URL: `{{system.today}}` is the date at session creation as ISO `YYYY-MM-DD`, and `{{system.timezone}}` is the resolved IANA name (`UTC` when nothing resolves). There is no `{{system.now}}`: variables render once, when the session is created, so a templated clock would freeze at the opening. The per-turn time above is the one to rely on.
## Which timezone a session uses
@@ -61,9 +61,11 @@ curl --request POST https://api.fish.audio/v1/agent/sessions \
agent's timezone for those. Calls that resolve nothing run in UTC.
-## Turn it off
+## Turn it on or off
-Time awareness is on by default. To withhold both the date and the per-turn time from a session (for example a role-play agent set on a fictional date, or a test that must be reproducible), set `world_context: false` when creating the session:
+**For the whole agent**, switch **Current date & time** in the Builder (**Configuration**, under the time zone) or set `context.current_time` through the [config API](/agents/build/configuration#current-date-and-time). This is the default for every session of the agent on every channel, and the only switch for phone calls, which the platform creates without a session request. Publish the agent for the change to reach live traffic. Turn it off again when the agent must not know the real date and time: a role-play agent set on a fictional date, a prompt that states its own date, or a test that must be reproducible.
+
+**For one session**, send `context.current_time` when creating it. An explicit value overrides the agent's setting in either direction: `false` withholds the date and time from an agent that has them on, `true` injects them for one session of an agent that has them off. The older `world_context` field (`worldContext` in the SDK) is still accepted as an alias.
```bash API (curl)
@@ -72,17 +74,17 @@ curl --request POST https://api.fish.audio/v1/agent/sessions \
--header "Content-Type: application/json" \
--data '{
"agent_id": "YOUR_AGENT_ID",
- "world_context": false
+ "context": { "current_time": false }
}'
```
```javascript JavaScript SDK
import { AgentSession } from "@fishaudio/agent-client";
-// Public agent: the SDK forwards the opt-out in its creation request.
+// Public agent: the SDK forwards the override in its creation request.
const session = await AgentSession.start({
agentId: "YOUR_AGENT_ID",
- worldContext: false,
+ context: { currentTime: false },
});
```
@@ -95,7 +97,7 @@ const session = await AgentSession.start({
icon="server"
href="/agents/deploy/authenticated-sessions"
>
- All session-creation parameters, including `timezone` and `world_context`.
+ All session-creation parameters, including `timezone` and `context`.
`overrides`, `dynamic_variables`, `tool_events`, `timezone`, and
- `world_context` belong in your backend's creation request. The SDK forwards
+ `context` belong in your backend's creation request. The SDK forwards
these options (and its `language` shorthand for `overrides.language`) only in
[public agent](/agents/deploy/public-agents) mode.
@@ -135,7 +135,7 @@ More on what the SDK can do once connected is in the [Web SDK](/agents/deploy/we
| `record_audio` | boolean, optional | Whether to record this session's audio. Overrides the agent's [recording setting](/agents/monitor/conversation-history#what-gets-stored) for this session only; omit it to use the agent's configuration. |
| `timezone` | string, optional | IANA timezone (like `Asia/Tokyo`) for the agent's sense of local time. Invalid names are rejected with `422`. See [Time & timezone](/agents/build/time-timezone). |
| `client_timezone` | string, optional | The end user's device timezone as an IANA name. A hint, not a demand: it applies only when neither `timezone` nor the agent's configured timezone is set, and invalid values are ignored. The SDK fills it automatically in public-agent mode. From your backend, forward the value from your client. See the [resolution order](/agents/build/time-timezone). |
-| `world_context` | boolean, optional | Whether the agent knows the current date and time. Default `true`; set `false` to withhold both from this session. |
+| `context` | object, optional | Per-session overrides of the agent's [context switches](/agents/build/configuration#context). `{ "current_time": false }` withholds the current date and time from this session, `true` injects them even when the agent has them off; omit a switch to follow the agent. `world_context` is a deprecated alias of `context.current_time`. |
Unknown fields (top-level or inside `overrides`) are rejected with `422`.
diff --git a/agents/deploy/web-sdk.mdx b/agents/deploy/web-sdk.mdx
index 6962b02..f49dde5 100644
--- a/agents/deploy/web-sdk.mdx
+++ b/agents/deploy/web-sdk.mdx
@@ -71,7 +71,7 @@ const session = await AgentSession.start({ sessionToken });
for `overrides.language` (`agentId` mode only). Omit it to use the agent's configured [speaking language](/agents/build/voice-language#speaking-language); any other value is rejected with `422` |
| `toolEvents` | `boolean` | Whether tool lifecycle events reach this client (default `true`; `agentId` mode only, with `sessionToken` your backend sets `tool_events`) |
| `timezone` | `string` | IANA timezone for the agent's sense of local time: the top of the [resolution order](/agents/build/time-timezone), overriding the agent's configured timezone. When omitted, the SDK still sends the browser timezone as a lower-priority hint (`client_timezone`), which applies only if the agent has no timezone configured |
-| `worldContext` | `boolean` | Whether the agent knows the current date and time (default `true`; `agentId` mode only, with `sessionToken` your backend sets `world_context`) |
+| `context` | `{ currentTime?: boolean }` | Per-session overrides of the agent's [context switches](/agents/build/configuration#context): `currentTime: false` withholds the current date and time, `true` injects them even when the agent has them off, omit it to follow the agent (`agentId` mode only, with `sessionToken` your backend sets `context`). `worldContext` is a deprecated alias of `context.currentTime` |
| `endUserId` | `string` | Your identifier for the end user, stored on the session and echoed in [webhooks](/agents/monitor/webhooks) (`agentId` mode only; with `sessionToken` your backend sets `end_user_id`) |
| `metadata` | `object` | Your own key-values, stored on the session record and returned verbatim (`agentId` mode only; with `sessionToken` your backend sets `metadata`) |
| `microphone` | `boolean` | Capture the microphone on start (default `true`). `false` joins muted with no permission prompt, for text-first UIs; the first `setMicMuted(false)` captures it, so call that from a user gesture |
diff --git a/agents/test/agent-tests.mdx b/agents/test/agent-tests.mdx
index fcb9f92..65893b2 100644
--- a/agents/test/agent-tests.mdx
+++ b/agents/test/agent-tests.mdx
@@ -217,7 +217,7 @@ Every Simulation field lives under `simulation`. An optional `conversation`, up
| Required tool calls | `assertions.tool_calls`: `tool`, `params`, `min_calls`, `max_calls` |
| Forbidden tools | `assertions.forbidden_tools` |
| Ended by | `assertions.ended_by`: `agent`, `user`, `transfer`, or `any` |
-| Current date and time | `world_context`: `true` or `false`, default `false` |
+| Current date and time | `context.current_time`: `true` or `false`, default `false` |
| Repeat | `repeat_count`, 1 to 20 |
Tools are referenced by `id`, `name`, and `type`, as in Tool tests, and integration tools use the `:` ids that [List Test Tools](/api-reference/endpoint/agent/list-test-tools) returns. Parameter conditions (`when` on a mock entry, `params` on a required call) map a parameter name to `{"type": "exact" | "regex" | "any", "value": "..."}`.
diff --git a/api-reference/openapi.json b/api-reference/openapi.json
index f1e2faf..eb47d25 100644
--- a/api-reference/openapi.json
+++ b/api-reference/openapi.json
@@ -1749,6 +1749,13 @@
}
],
"default": null
+ },
+ "llm_endpoint_errors": {
+ "items": {
+ "$ref": "#/components/schemas/AgentSessionLlmEndpointError"
+ },
+ "title": "Llm Endpoint Errors",
+ "type": "array"
}
},
"required": [
@@ -19071,6 +19078,114 @@
"title": "AgentSessionAnalysisResult",
"type": "object"
},
+ "AgentSessionLlmEndpointError": {
+ "description": "One failed reply from the customer's own LLM endpoint, after the\nplatform's single retry within the request.\n\n- http_error: the endpoint answered with a non-2xx status.\n- timeout: no response within the request timeout.\n- connection_error: the request got no answer. `reason` is dns_failed,\n connection_refused, connection_reset, tls_failed, address_not_allowed\n (an address the platform does not call) or unknown.\n- invalid_response: a 2xx response that was not a usable reply. `reason`\n is not_event_stream (a streamed request answered with something else),\n stream_incomplete (the stream ended without a finish_reason, usage or\n output), empty_reply (no text and no tool call) or unknown.",
+ "properties": {
+ "occurred_at": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Occurred At"
+ },
+ "turn_id": {
+ "anyOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Turn Id"
+ },
+ "type": {
+ "enum": [
+ "http_error",
+ "timeout",
+ "connection_error",
+ "invalid_response"
+ ],
+ "title": "Type",
+ "type": "string"
+ },
+ "reason": {
+ "anyOf": [
+ {
+ "enum": [
+ "dns_failed",
+ "connection_refused",
+ "connection_reset",
+ "tls_failed",
+ "address_not_allowed",
+ "not_event_stream",
+ "stream_incomplete",
+ "empty_reply",
+ "unknown"
+ ],
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Reason"
+ },
+ "status_code": {
+ "anyOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Status Code"
+ },
+ "response_body": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Response Body"
+ },
+ "duration_ms": {
+ "anyOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Duration Ms"
+ },
+ "consecutive_failures": {
+ "title": "Consecutive Failures",
+ "type": "integer"
+ }
+ },
+ "required": [
+ "type",
+ "consecutive_failures"
+ ],
+ "title": "AgentSessionLlmEndpointError",
+ "type": "object"
+ },
"AgentSessionMessageItem": {
"description": "One transcript message; system messages never surface here.",
"properties": {
@@ -19152,6 +19267,19 @@
"default": null,
"title": "Input Medium"
},
+ "fallback_reason": {
+ "anyOf": [
+ {
+ "const": "llm_error",
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Fallback Reason"
+ },
"turn_id": {
"anyOf": [
{
@@ -21205,6 +21333,22 @@
"default": null,
"description": "Sent to your endpoint as the Authorization bearer token; write-only, reads return null. Required when introducing `custom`; omit to keep the stored key when updating.",
"title": "Api Key"
+ },
+ "headers": {
+ "anyOf": [
+ {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "description": "Extra headers sent on every request to your endpoint, such as `x-vercel-protection-bypass`; write-only, reads return null. Omit to keep the stored headers, `{}` clears them.",
+ "title": "Headers"
}
},
"required": [
@@ -22345,7 +22489,7 @@
"type": "object"
},
"AgentLLMCustomConfigRedacted": {
- "description": "Read entity: the stored api_key never leaves the collection.",
+ "description": "Read entity: the stored api_key and headers never leave the collection.",
"properties": {
"base_url": {
"minLength": 1,
@@ -22361,6 +22505,11 @@
"default": null,
"title": "Api Key",
"type": "null"
+ },
+ "headers": {
+ "default": null,
+ "title": "Headers",
+ "type": "null"
}
},
"required": [
@@ -23186,6 +23335,13 @@
"default": false,
"title": "Passed",
"type": "boolean"
+ },
+ "llm_endpoint_errors": {
+ "items": {
+ "$ref": "#/components/schemas/AgentSessionLlmEndpointError"
+ },
+ "title": "Llm Endpoint Errors",
+ "type": "array"
}
},
"title": "AgentTestSimulationResult",