Skip to main content

falaw

Agent-friendly Python facade over fal.ai for generating and managing AI media (images, video, audio).

from falaw import generate_image, list_models, journal

r = generate_image("a tiger eye, macro, 35mm", quality="fast")
r.first.download(to="./tiger.png")

[m.id for m in list_models(category="video")]
journal.note("schnell at quality='fast' defaults to 1024x1024")

Why

fal-client already gives you 100+ models behind a uniform call. What agents (and humans) still struggle with is which model to use, what parameters it takes, and what to do with the URL it returns. falaw adds:

  • Task-level verbs (generate_image, text_to_speech, ...) with smart model selection by quality tier.
  • A queryable model registry --- no more grepping docs for IDs.
  • Result / Asset objects that download, name, and organize outputs.
  • A journal so each session leaves notes for the next one.
  • A Claude skill, plus stub bridges for MCP and HTTP services --- all derived from the same tool registry.

Install

pip install -e .
export FAL_KEY="your-fal-api-key"

Core surface

Function Purpose
generate_image(prompt, *, quality, image_size, model_id, extra) Text-to-image, picks FLUX by quality tier.
text_to_speech(text, *, quality, voice, model_id, extra) TTS, picks a voice model by tier.
list_models(*, category, quality_tier) Browse the catalog.
pick_model(*, category, quality_tier) Pick a sensible default.
call_fal(application, arguments, *, on_event) Escape hatch to any fal model. Emits ProgressEvents + auto-journals on error.
cached_call_fal(...) Same, plus content-addressed cache; emits cache_hit events on reuse.
render_scene(scene, *, concurrency=N) / iter_render_scene(...) Render every shot+beat; thread-pooled, with yield-as-done iterator.
estimate_scene_cost(scene) Walk a Scene, return a CostRollup with per-line USD breakdown.
subscribe(callback) Attach a global subscriber to the ProgressEvent bus.
journal.note / issue / improvement(...) Leave a trace for future sessions.
Session(output_dir=...) Optional stateful controller.

Structured progress events

call_fal and cached_call_fal emit ProgressEvents at every lifecycle transition (queued, progress, log, done, error, cache_hit). Subscribe per-call (on_event=) or globally (falaw.subscribe(...)); the legacy on_log=print is still honored for backward compatibility.

from falaw import subscribe, generate_image

subscribe(lambda ev: print(f"[{ev.kind}] {ev.application} {ev.elapsed_s:.2f}s"))
generate_image("a tiger eye", quality="fast")

Cost estimation

ModelRecord.cost_estimate: CostEstimate | None carries a structured {kind, amount, currency} price (kinds: per_call | per_image | per_second | per_token | per_megapixel). estimate_scene_cost(scene) sums per-call costs and returns a CostRollup with per-line breakdown. Models without a populated cost_estimate appear in the rollup's skipped list so audits surface drift.

Concurrency

render_scene(..., concurrency=4) runs shots and beats in parallel through a thread pool (fal calls are HTTP-bound). Default concurrency=1 preserves serial behavior. Use iter_render_scene(...) to yield (kind, result) pairs as each unit completes — handy for live UI updates.

Architecture

Single source of truth: a ToolSpec dataclass per tool. From it we derive every external surface:

falaw.registry  ──► bridges/skill.py    ──►  .claude/skills/falaw/SKILL.md
                ──► bridges/mcp.py      ──►  MCP server          (planned)
                ──► bridges/service.py  ──►  qh HTTP service     (planned)
                ──► (UI)                                          (planned)

Adding a new surface is a new bridge module, never a re-implementation of the operations.

Self-improvement loop

Every session can read and write the agent journal at ~/.config/falaw/journal/. The Claude skill instructs Claude to:

  1. Read recent entries before novel work.
  2. Write a note / issue / improvement when something surprises it.

call_fal auto-journals failures with the application id and arguments, so the next session recognizes the trap.

Layout

falaw/
  base.py            ToolSpec, ModelRecord
  core.py            call_fal: subscribe + auto-journal
  registry.py        register_tool, list/get/pick model
  results.py         Asset, Result, parse_response
  session.py         Session
  journal.py         file-backed journal
  operations/
    images.py        generate_image
    audio.py         text_to_speech
  bridges/
    skill.py         render Claude SKILL.md from registry
    mcp.py           (stub)
    service.py       (stub)
  data/
    models.json      seed catalog
    skills/falaw/    generated skill files (shipped with package)
misc/
  docs/              aggregated fal.ai docs (3MB md, llms.txt, llms-full.txt)
  regenerate_skill.py
tests/

Regenerate the skill after adding a tool

python misc/regenerate_skill.py

Writes falaw/data/skills/falaw/SKILL.md and .claude/skills/falaw/SKILL.md.

Status

v0 --- functional core, real Claude skill, stubs for MCP and HTTP service. The bridges share the same registry, so filling in the stubs is additive.

Roadmap

See misc/docs/roadmap.md for the ordered work and the standing constraints. In short, four tracks:

  1. Content addressing --- Artifact.asset_id and the per-call cache key are currently derived from the fal CDN URL, not from the bytes. fal states that every upload gets a unique URL and that expired files are permanently deleted, so today a byte-identical regeneration misses the cache and a stored response decays into a dead link. The fix routes through lacing.ArtifactStore.put_blob.
  2. Backend-parametric Plan --- CallPlan.backend + registry dispatch in execute_plan, so a second execution backend is still priced, cached and dry-runnable.
  3. Licence-and-terms ledger --- per (model, backend), queried at plan time, unknown means refuse.
  4. Cost data from the vendor --- read fal's pricing API instead of hand-maintaining data/models.json (19 of 40 records currently carry no structured price at all).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

falaw-0.0.24.tar.gz (1.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

falaw-0.0.24-py3-none-any.whl (106.3 kB view details)

Uploaded Python 3

File details

Details for the file falaw-0.0.24.tar.gz.

File metadata

  • Download URL: falaw-0.0.24.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for falaw-0.0.24.tar.gz
Algorithm Hash digest
SHA256 2eee1f819b76d2b79f14fa5c1f0ecae28ccf8003f285dcdda8698e8c8038828d
MD5 d6cfa3812f5b0bfcf55f994eaafa9adf
BLAKE2b-256 1a0ac0a714fdcca7ff60c813e8393d447ccdd4b449255d2a4eb3852549221721

See more details on using hashes here.

File details

Details for the file falaw-0.0.24-py3-none-any.whl.

File metadata

  • Download URL: falaw-0.0.24-py3-none-any.whl
  • Upload date:
  • Size: 106.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for falaw-0.0.24-py3-none-any.whl
Algorithm Hash digest
SHA256 6d5acfb76bdc5a036965477bdbf1cb1c76832b1a9168a63c82662e152676f3c8
MD5 5e5681c0aba23e53f41c69780802ae61
BLAKE2b-256 173c87a1d5ca070a42065c8a83de87c428d4731df72238ce83218d2fc238ad1d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page