From functions to action.
Python operations and verifiable workflows for humans, automation, and AI agents.
Docs · Quick Start · Agents · Install
What is Functualize?
Functualize turns ordinary Python functions into discoverable, configurable, composable operations and verifiable workflows.
Use the same underlying jobs from the TUI, CLI, Python, MCP, HTTP, Lambda, CI, an AI agent, or another workflow.
function → job → workflow → evaluation → outcome
The CLI is only one surface. The underlying operation stays the same.
Quick Start
Drop a function into your workspace:
# deploy.py
from functualize.job import RunContext
def deploy(environment: str = "staging", rc: RunContext | None = None) -> None:
if rc:
rc.log(f"Deploying to {environment}...")
From that directory:
func
func discovers the workspace and opens the interactive TUI, where you can
find jobs, inspect/configure parameters, see where values come from, and run them.
Or invoke directly:
func deploy --environment production
No command-registration boilerplate is required.
Why Functualize?
A useful function is easy to write. Making it operational usually adds:
- discovery and invocation
- typed configuration
- secret and credential provisioning
- local and remote config / secret sources
- dependency injection
- structured logging and execution context
- state and resumability
- workflows and conditional execution
- human or AI gates
- verification and completion criteria
- multiple delivery surfaces
Functualize provides that layer while keeping domain logic as ordinary Python.
Workspace-native operations
Functualize can attach an operational layer to an existing repository without taking over its application structure.
workspace/
├── src/
├── docs/
├── AGENTS.md
└── .functualize/
├── jobs/
├── lib/
└── plugins/
This works whether the repository itself is Python, Go, Rust, Terraform, research code, or a mixed agent workspace.
Functualize can combine workspace-local jobs with user-global jobs under
~/.config/functualize/jobs/, following the XDG configuration convention.
Additional job directories can also be configured explicitly.
Built for the agent workspace
An emerging pattern in agent systems is to treat the workspace itself as a first-class interface: files hold context and artifacts, directories provide structure, and agents use the filesystem and shell to understand and act on their environment.
You can see this direction in ICMP / Model Workspace Protocol, OpenClaw, Hermes Agent, and Vercel's filesystem-first agent work.
Functualize makes the executable side of that pattern straightforward: keep
context and artifacts in the workspace, put reusable operations under
.functualize/, and let humans or agents discover and invoke them from the same
place.
The workspace provides context. Functualize gives it executable, composable operations.
Agents and workflows
Functualize complements agents rather than replacing them.
Keep your agent. Give it reliable workflows.
The agent supplies reasoning. Functualize supplies the procedure, state, gates, allowed transitions, deterministic checks, and completion criteria.
Agent / harness
│
▼
Functualize workflow
│
├── deterministic step
├── agent step
├── verification gate
├── correction
└── evaluator
│
▼
verified outcome
Drive a workflow over CLI
Start the workflow like any other job:
func release
If it blocks on a gate in non-interactive mode, Functualize persists the scope. Inspect, answer, and resume the same workflow:
func builtin workflow list
func builtin workflow show <workflow-id>
func builtin workflow answer <workflow-id> <gate> --input '{"approved": true}'
func builtin workflow resume <workflow-id>
Or answer and advance in one command:
func builtin workflow resume <workflow-id> --input '{"approved": true}'
Completed steps are not re-run; recorded branches and gate inputs remain stable when the workflow resumes.
Or drive the same workflow over MCP
Expose the workspace:
func mcp serve
An agent can discover and start a workflow through the normal MCP job tools:
discover_jobs()
get_job_schema("release")
run_job("release")
If it blocks:
list_workflows()
get_workflow_state("<workflow-id>")
The agent can inspect the pending gate, use tools offered by that gate, provide input, and advance the same workflow:
call_gate_tool("<workflow-id>", "inspect_artifact", {...})
answer_gate({...}, workflow_id="<workflow-id>", gate="review")
resume_workflow("<workflow-id>")
Or provide the gate input directly while resuming:
resume_workflow(
"<workflow-id>",
input={"approved": true, "reason": "checks passed"}
)
The distinction is simple:
answer_gate(...) records gate input
resume_workflow(...) advances the workflow
This gives agents a stable loop:
discover → start → inspect → act → resume → verify → complete
without requiring a specific agent framework or model.
Bring your own agent. Bring your own model. Bring your own harness. Standardize the workflow.
What you get
- Discovery — CWD,
.functualize/, explicit directories, and user-global jobs - Configuration — typed config, layering, remote sources, secrets
- Execution —
RunContext, DI, lifecycle, stable exit semantics - Workflows — DAGs, gates, state, resume,
AgentStep, evaluation - Agents — MCP tools, AI gates, agent-backed steps, verifiable execution
- Surfaces — TUI, CLI, Python, MCP, HTTP, Lambda
- Extensibility — plugins, providers, adapters, domain SDKs
Installation
Standalone — no system Python required
curl -LsSf \
https://raw.githubusercontent.com/raicing-ai/functualize/master/install.sh \
| sh
Windows:
irm https://raw.githubusercontent.com/raicing-ai/functualize/master/install.ps1 | iex
The standalone distribution includes its own Python runtime and first-party Functualize components.
Then simply run:
func
With Python
uv tool install "functualize[cli]"
or:
pipx install "functualize[cli]"
As a library
uv add functualize
Use FunctualizeApp when you want to build your own named CLI/application on
top of the runtime, with explicit job sources, configuration, plugins, and
delivery adapters.
from functualize.app import FunctualizeApp, JobSources, classic
app = FunctualizeApp(
name="my-ops",
job_sources=JobSources(directories=["my_ops.jobs"]),
config_sources=classic(),
)
def run() -> None:
app.run()
Extend Functualize
Functualize supports packaged plugins through Python entry points, and a
workspace can keep project-local extensions under .functualize/plugins/ so
shared behavior can live with the repository and augment operations contributed
by multiple job authors.
Plugins can add lifecycle hooks, CLI commands, dynamic jobs, providers, adapters, and other integrations without changing Functualize core.
Core concepts
| Concept | Meaning |
|---|---|
| Function | Ordinary Python domain logic |
| Job | A discoverable, configurable executable function |
| Workflow | Jobs and agent steps composed into a bounded procedure |
| Evaluation | Gates, checks, tests, and postconditions |
| Operation | Useful work that can be invoked and executed reliably |
| Delivery surface | TUI, CLI, Python, MCP, HTTP, Lambda, or another adapter |
Documentation
Project status
Functualize is currently alpha and actively evolving around workflows, agent interoperability, evaluation, secrets/configuration, and adapters.
Contributing
See Contributing.
License
Apache 2.0 © 2025-2026 Mohammad Hakim Adiprasetya
Release files for functualize 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| functualize-0.3.0.tar.gz | 1.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| functualize-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.6 MB
Release files / functualize-0.3.0.tar.gz
| Download URL | functualize-0.3.0.tar.gz |
|---|---|
| Size | 1.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d78ee3cbffbacab2b54564575c49fa9b3fb3d8607286899ff8c0a93c5c9c95c1
|
|
BLAKE2b-256 checksum How to use checksums |
c0c5977b662723a7d7ae875485ed88192354cb408af606ec0498ee1e7e718b01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / functualize-0.3.0-py3-none-any.whl
| Download URL | functualize-0.3.0-py3-none-any.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
feaa15b90b78fd3df5ad85c58b0798fb13432080b2cf107e87f6c3856209e455
|
|
BLAKE2b-256 checksum How to use checksums |
1385f999503b079a5bf1b48b51ff24ce712c5b5167fabddcb0de4aa0a190cd7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency log