Nodetool FAL Node Writer
Overview
Generate nodetool-fal node classes from Fal llms.txt model docs while matching current repository conventions.
Workflow
- •Require at least one
llms.txtURL. - •Analyze current Fal implementations before generating code.
- •Parse each URL and generate a scaffold class.
- •Refine scaffold to match neighboring module style.
- •Validate with formatting/lint/tests when requested.
Step 1: Require URL Input
Accept URLs in this format:
- •
https://fal.ai/models/<publisher>/<model>/llms.txt - •
https://fal.ai/models/<publisher>/<model>/<variant>/llms.txt
If user gives a model page/API URL, convert it to .../llms.txt first.
Step 2: Analyze Existing Fal Modules First
Always inspect all Fal node files before writing code so generated nodes follow current patterns, defaults, and naming.
Run:
rg -n "^class .*\(FALNode\)|async def process|get_basic_fields|application=|image_to_base64|client.upload|return .*Ref" src/nodetool/nodes/fal/*.py
Then read:
- •
references/nodetool-fal-patterns.mdfor mental model and conventions. - •
src/nodetool/nodes/fal/fal_node.pyfor base request behavior.
Step 3: Generate Scaffold from llms.txt
Use bundled script:
python3 scripts/scaffold_fal_node.py "<llms.txt-url>"
For multiple URLs:
python3 scripts/scaffold_fal_node.py "<url-1>" "<url-2>"
Script behavior:
- •Fetch
llms.txt. - •Extract model metadata (
Model ID, category, input schema, output schema). - •Infer field types and enum candidates.
- •Emit a
FALNodeclass scaffold withField(...),process(...), andget_basic_fields.
Scaffold limitations (fix manually or in post-processing):
- •List/array params — The script infers a generic
listtype. It does not parselist<SomeCompoundType>(e.g.list<KlingV3MultiPromptElement>,list<KlingV3ComboElementInput>). Those appear in llms.txt as a single bullet (e.g.elements,multi_prompt) with type likelist<...>and no per-item structure in the doc, so the script does not emit list-of-object handling. - •Compound objects — Params like
elements(frontal_image_url + reference_image_urls, or video_url) are not broken down. The scaffold may omit them or treat them as a simple list; you must add proper fields and build the payload from the OpenAPI schema. - •Conditional / paired params — e.g.
shot_typerequired whenmulti_promptis provided. The script does not encode “only include when X is set”; add conditional logic when merging scaffold into the repo. - •Single-option enums — e.g.
shot_typewith only"customize". The script may still emit an enum; if the API has only one valid value, you can omit the field and send the value when the paired feature (e.g. multi_prompt) is used.
Step 4: Refine to Repository Style
After scaffold generation, cross-check the OpenAPI for the exact endpoint (https://fal.ai/api/openapi/queue/openapi.json?endpoint_id=<ENDPOINT_ID>). Add or fix any list-of-object or compound params (e.g. elements, multi_prompt) and conditional fields (e.g. shot_type when multi_prompt is used) that the scaffold did not emit. Then enforce these conventions:
- •Inherit from
FALNode. - •Use media refs (
ImageRef,VideoRef,AudioRef,Model3DRef) for media inputs/outputs. - •Convert image refs with
context.image_to_base64(...)and send as data URIs. - •Upload video/audio bytes when endpoint requires uploaded files rather than URLs.
- •Build
argumentswith optional-field guards. - •Extract outputs using existing patterns (
res["video"]["url"],res["images"][0]["url"], etc.). - •Implement
get_basic_fields()with top-priority fields.
If an endpoint shape is ambiguous, match the nearest existing node in the same modality file (text_to_image.py, image_to_video.py, text_to_video.py, etc.).
Step 5: Placement and Follow-up
Add the class to the correct node file under:
- •
src/nodetool/nodes/fal/
Then suggest the standard follow-up commands:
nodetool package scan nodetool codegen ruff check . black --check . pytest -q
Use nodetool package scan and nodetool codegen whenever node definitions changed.
Important: Validation checklist (from AGENTS.md)
Before considering a node done, verify:
- •Field names match the API exactly — Check OpenAPI:
https://fal.ai/api/openapi/queue/openapi.json?endpoint_id=<ENDPOINT_ID> - •Only send fields the API supports — Variants (e.g. V3 vs O3) have different parameters.
- •Never send
Noneto the API — Optional strings from the UI can beNone; sendingnullcausesinput_value_error. Guard with:pythonif self.negative_prompt is not None and self.negative_prompt.strip(): arguments["negative_prompt"] = self.negative_prompt - •Compound objects — Include every required sub-field the schema expects.
- •Enums — Do not reuse across API variants without checking; each endpoint may support different values.
- •Variants — Treat Standard/Pro or V3/O3 as separate APIs; re-check schema for the exact endpoint.
- •Docstring Format: First line describes the model, second line contains comma-separated tags, followed by use cases
- •Field Descriptions: Use clear, descriptive text from the OpenAPI schema
- •Default Values: Set sensible defaults based on schema defaults
- •Optional Fields: Handle conditional arguments properly
- •Error Handling: Always assert expected output fields exist