Functions
A function is a tool an agent can call. Without functions an agent can only read and write text. With them it can query an API, run code, read files, open a pull request or hand work to another agent.
You manage functions under Resources → Functions. The page lists every function in the current project as a tree (the Function Library). You organise it into folders by dragging items.
How an agent uses a function
- When a chat or workflow run starts, the platform builds the agent's tool list from the functions assigned to it. Each tool has a name, a description and a parameter schema.
- The model reads those descriptions and decides whether to call a tool, and with what arguments.
- The platform checks policy and approval settings, runs the call, and returns the result to the model.
- The loop repeats until the agent has what it needs.
The name and description are what the model sees, so they decide whether the tool gets used at all. Write the description for a reader who cannot see the code: say what the tool does, when to use it and what it returns.
Function types
| Type (as shown in the app) | What it is | How you create it |
|---|---|---|
| Wrap an integration operation (stored as Local Python) | Generated Python that calls one operation declared on an integration. The credential is resolved by the platform and never enters the function. | New function chooser (recommended) |
| Local Python | Python you write. It runs in an isolated sandbox worker, one fresh process per call. | New function chooser |
| MCP server (MCP Stdio) | A Model Context Protocol server started as a subprocess, for example npx -y some-mcp-server. One function can expose many tools. | New function chooser |
| MCP over HTTP | A remote MCP server reached over HTTP. One function can expose many tools. | New function chooser |
| Skill (SKILL.md) | Markdown instructions the model can activate when relevant. A skill is prompt text, not code, so it cannot be test-run. | New function chooser, or Import Skill |
| Execution environment tool | Tools served by an execution environment or local runner. | Created from the environment or runner side |
| Platform built-in | A tool whose implementation ships with the platform. The row exists so the tool can be assigned and given an approval setting. Read-only. | Platform-provided; see Built-in Tools |
The API also accepts an agent_reference function type, which runs another agent as a sub-agent. The Functions page has no editor for it: such functions are created from templates or through the API, and the page displays them as Local Python. To delegate between agents in the app, see Agents and Teams.
Brokered vs direct calls
FYAI distinguishes two ways a function can reach an external service:
- Brokered. The function calls
capabilities.call("operation_name", integration=..., ...). The platform checks that the run is allowed to use that integration and operation, injects the credential, makes the request and returns the response. The function body never holds a secret, and it can only reach hosts the integration allows. - Direct. The function reads a secret (or an environment variable) and calls the API itself, for example with
aiohttp. This still works, but the Definition tab flags it as direct egress, and any secret-shaped parameter (such asGITHUB_TOKEN) is flagged as something a prompt could fill in.
Wrapping an integration operation produces a brokered function with no code to write. It is the first option in the chooser for that reason.
What a Local Python function can and cannot do
The sandbox in two paragraphs. Every call of a Local Python function runs in a fresh process in a shared worker pod, under a kernel identity of its own for that session. The environment is scrubbed to a short allow-list (PATH, HOME, the platform service addresses and similar), the application source is sealed so only the SDK modules are readable, and the process holds no database credentials, no cluster credentials and no platform secrets.
Anything that crosses the boundary goes through something the platform controls: integration secrets and requests through the broker, platform operations through a capability the run is minted and Allowed Operations narrows, and files through the session's workspace. That is why a function that works on a laptop by reading an environment variable or opening a database connection fails here.
It can import the standard library and the packages installed in the worker image; use IntegrationWrapper and the other app.utils helpers; call platform_api.call(service, operation, ...) for the operations it lists under Allowed Operations; and take its configuration as parameters.
It cannot import any other app.* module (app.dependencies, app.models, app.services.*), connect to the platform database or to cluster addresses (*.svc, *.cluster.local), read platform environment variables such as DATABASE_URL, a service's *_INTERNAL_SECRET, VAULT_* or KUBERNETES_*, read /proc/*/environ or /var/run/secrets, run cluster tooling such as kubectl or psql, or carry a literal credential.
What the platform checks when you save
When code is created or changed the platform reads it (nothing is executed) and lists what it found: a rule id, the line, what is wrong and what to use instead. The check applies to every way code arrives: creating and editing a function, importing a stack, promoting between projects, rolling back a revision, installing a blueprint and running a test.
| Rule | Severity | Finds |
|---|---|---|
| FC001 | Error | an import from app.* outside the SDK |
| FC010 | Error | a database client (psycopg2, asyncpg, sqlalchemy, pymongo, redis) used with a platform hostname, DATABASE_URL or a platform environment variable |
| FC020 | Error | a read of a platform environment variable with no default and no other path |
| FC023 | Error | /proc/*/environ, /var/run/secrets and similar paths |
| FC030 | Error | a cluster-internal address or the metadata endpoint |
| FC040 | Error | a subprocess that runs kubectl, psql, helm, vault and similar |
| FC050 | Error | a literal credential in the code |
| FC021, FC022, FC024 | Warning | an environment read that will be missing; the whole environment enumerated; a platform variable read that has a fallback |
| FC031 | Warning | a direct request to a platform public API address, which carries no credential |
| FC060 | Warning | a while True loop with no break, return or raise |
Findings come back with the saved function as contract. How an Error is treated is a platform setting: while the platform audits, the function is saved and the findings show what would be refused; when it enforces, the save is refused with the same text and nothing is stored. A warning never refuses. A data source that names a function with an error is refused or flagged the same way.
How functions use integrations
A function reaches external services through the integrations linked to it. On the function's Definition tab, under Authority:
- Link Integration attaches one or more integrations. A function can link several, and an integration can be linked to many functions.
- Allowed Operations lists the operations this function may call through the broker. You pick them from the operations the linked integrations declare. If none are granted, the function cannot make brokered calls ("No operations granted — this function cannot make credentialed calls").
What a linked integration provides depends on the function type:
| Function type | What the linked integration supplies |
|---|---|
| Local Python, brokered | Authority to call the granted operations; the credential stays with the platform. |
| Local Python, direct | Secrets readable from code (legacy pattern, flagged on the Definition tab). |
| MCP Stdio | Every secret and environment variable of the linked integrations is passed to the subprocess as an environment variable named after it. |
| MCP over HTTP | {{SECRET_NAME}} placeholders in Headers are filled from linked secrets. A linked secret with no matching header is added as a header named after the secret. |
An agent can also be told to use a different integration's account for a tool (for example, so a GitHub approval comes from a different user). That is set per agent under Tool Identity. See Agents.
Approval
Each function has an Approval Override:
| Option | Effect |
|---|---|
| Inherit from risk appetite (default) | Whether a call needs human approval is decided by the function's risk level against the organisation, project or personal risk-appetite tier. |
| Always require (pin) | Every call pauses for approval. |
| Never require (pin) | Calls run without approval. |
When pins disagree, a team pin wins over an agent pin, which wins over a function pin. One guarantee overrides every pin: a call whose combined risk is critical still requires approval unless the risk appetite is set to bypass all approvals. Platform policy can also refuse to attach a tool at all.
For MCP functions you can also pin approval per tool in the Discovered tools table. See Using Approval Gates and Governance.
Killswitch
Every saved function has an Active / Killed switch in its header. Killing a function stops it being built or run anywhere on the platform until it is reactivated, and locks its configuration read-only.
Function page tabs
| Tab | What it shows |
|---|---|
| Overview | Reach, effective policy and references at a glance. |
| Definition | The editor. For Local Python: the code workbench with a live console. For MCP: server settings, health, discovered tools, egress, approval and secrets. Also holds Authority (linked integrations, allowed operations, Internal). |
| Details | Name, description, type, approval override and tags. |
| Consumers | Agents, teams and workflows that use the function, with a what-if view of the impact of a change. |
| Topology | A graph of how the function connects to agents, integrations and hosts. |
| Test | The test console (MCP and other non-Python types; Local Python has the console on the Definition tab). |
| Observability | Runtime telemetry for this function. |
| Risk | Risk classification used by approval and governance. |
| Controls | Governance controls mapped to this function. |
| History | Saved versions, with rollback. |
Platform-managed functions
Functions instantiated from a platform template show a platform badge and Managed by platform — read only. Only platform administrators can edit or delete them. Copy one with Copy Function if you need your own variant.
Turning a function into a data source
Create Data Source on a function opens Create Data Source from Function, which wraps the function as a reusable data source for dashboards and workflows. You give it a name, the integrations that supply credentials, a Refresh mode (On demand or Scheduled (interval), minimum 60 seconds, default 900) and optional static arguments as JSON. Create & Test creates the data source and runs a test fetch.
Related
- Function Settings: every field and action
- Creating Custom Functions: wrap an operation, write Python, import a skill
- Connecting an MCP Server
- Testing Functions
- Integrations: credentials and operations
- Adding Tools to Agents: assigning functions
- Choosing How to Add Knowledge