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.23.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.23-py3-none-any.whl (93.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: falaw-0.0.23.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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.23.tar.gz
Algorithm Hash digest
SHA256 bafaa2a35fc7dac62aa0613b8203e408fec02ab9cb848163231015574b0a2d41
MD5 c178ad1b4d2c5a261e5db0a054097587
BLAKE2b-256 7ace7d224978aaba2aee6d2085e4141678b3eccc671f9ebfe65ed6ff34f0b89b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: falaw-0.0.23-py3-none-any.whl
  • Upload date:
  • Size: 93.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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.23-py3-none-any.whl
Algorithm Hash digest
SHA256 e47cdffea7f55736fbc6b82be9583bd4cf2ae089058e4146fb44c2911996c6c5
MD5 e56fdf9d1e2b315bf29371d5a3493a99
BLAKE2b-256 38af9bb6f90eeb7f82cb7b3619d7e10757ae1f3620d7249477eae2e2a394c580

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