extract_functions_from_loaded_module is the single owner of the “walk a loaded module and collect its callables into a name → callable registry” rule that PraisonAI uses internally — reuse it when you already have a loaded module.
Quick Start
1
Simple — point an agent at a folder of tools
Drop a
tools.py next to your recipe/workflow YAML and set the gate. PraisonAI loads its public functions automatically — no import needed.2
Programmatic — load and register a module yourself
Load the module with the safe loader, extract its callables, then hand the values to
Agent(tools=...).3
Filter the walk
Two independent knobs narrow what the walk accepts.
How It Works
The helper walks the module’s members, applies the filter, and returns aname → callable dict for the caller to register.
The helper does not load anything — the caller owns the loading step (via the safe loader). If you only have a file path and no module object, use the path-based sibling instead.
Both share the same _accept rule, so the extraction behaviour is identical — the only difference is who owns the loading step.
Which entry point should I use?
Pick the entry point that matches what you already hold.Filter Reference
Both knobs default toFalse and can be combined.
With defaults, the walk accepts any member where
inspect.isfunction(obj) or callable(obj) is true. Order follows inspect.getmembers(module) (alphabetical by name).
Common Patterns
- A recipe tools.py
- A programmatic loader
- Combining with ToolResolver
The recipe/workflow loader picks up Internally the loader runs
tools.py automatically when the gate is on, then keeps an own-module origin filter so re-exports from other modules stay out of the registry.extract_functions_from_loaded_module(tools_module, functions_only=True, skip_private=True) and then keeps only members where inspect.getmodule(obj) is tools_module.Best Practices
Load with the safe loader, not importlib.import_module
Load with the safe loader, not importlib.import_module
Use
praisonai_code._safe_loader.load_user_module to stay inside the PRAISONAI_ALLOW_LOCAL_TOOLS gate and CWD path constraints. extract_functions_from_loaded_module deliberately does not load — the caller must.Use skip_private=True when your module has internal helpers
Use skip_private=True when your module has internal helpers
Prevents
_normalize_input and friends from leaking into the agent’s tool list.Reach for the module-level helper when you already have the loaded module
Reach for the module-level helper when you already have the loaded module
Loading a second time by path breaks
inspect.getmodule(obj) is my_module origin filters — object identity is what matters. Pass the module you already have.Add an origin filter if your module re-exports from elsewhere
Add an origin filter if your module re-exports from elsewhere
Keep re-exported callables from other modules out of your registry, exactly like the recipe loader does.
Related
Tool Resolver
The path-based sibling — loads + walks in one step
Local Tools Loading
How the
PRAISONAI_ALLOW_LOCAL_TOOLS gate loads your tools.pyTools (CLI)
Verify what got picked up with
praisonai tools listTools
General Tools concept overview

