Every enrichment platform eventually hits the wall where the user has a use case the platform doesn't have a built-in action for. The traditional response is "file a feature request and wait." The Clay-era response is "write a formula in our DSL." The TexAu response is Custom Functions — drop in JavaScript or Python, call any API, transform any column, and run inside the same workflow as native actions, with the same orchestration, billing, and audit trail.
The action surface is two primitives that compose to almost everything. Run JavaScript executes a sandboxed JS function with the row context and any fetch calls you need. Run Python does the same for Python with the standard library and a curated allowlist of packages (requests, pandas, numpy, pydantic). Both have access to environment variables and secrets you've configured at the workspace level, so calling a custom API doesn't require hardcoding a key.
The execution model is sandboxed-per-call. Each invocation runs in an isolated container with a strict memory and runtime ceiling — typical limits are 512 MB and 30 seconds, override-able for paid tiers. The container has outbound HTTP access (so you can call any API) and no inbound or filesystem access. Code does not persist across invocations; if you need state, you explicitly read from and write to a TexAu workspace store.
The cost model is per-second of runtime, not per-call, which keeps small functions cheap and bills heavy compute fairly. Most custom functions complete in under 500 ms and cost in the noise. Heavy ML inference or large data transforms are the exception and we surface that on the workspace billing.
The high-leverage patterns we see most:
Custom enrichment. Your team has a contract with a niche provider — a regional data source, a specialty API, an in-house signal feed — that doesn't have a TexAu action. Custom Functions wraps it. You write a 20-line JS function that takes the row, calls your provider, and returns the enriched fields. The rest of the workflow doesn't know it's a custom function — it looks like any other action.
Custom transformations. The output of one action doesn't quite match the input shape of the next. A native "shape this column" action would be its own product; Custom Functions makes it a one-liner. You write row.email = row.email.trim().toLowerCase() and ship.
Custom routing. ICP score thresholds change by region, by deal cycle stage, by quarter. A static "route by score" action is a feature request. A 30-line Custom Function that reads from your workspace store and routes accordingly is the actual answer.
Custom integrations. Your CRM is a regional one we don't natively support yet — Freshsales, SugarCRM, a homegrown system with a REST API. Custom Functions calls it directly. The rest of your workflow runs on native actions; only the CRM sync is custom.
Custom Functions is also the safety valve for the platform's roadmap. We can't build every action every customer needs. Custom Functions means you don't wait for us — you write the logic you need, ship it today, and we promote the most common patterns into native actions over time. Several of today's native actions started as customer-written Custom Functions we observed running at scale.