Model or dataset
typedef-ai/fenic avatar
typedef-ai/fenic

All three of fenic's code samples stop mid-constructor

Semantic DataFrames for humans and agents

673 stars43 forksPythonApache-2.0

At a glance

What is it?
A PySpark-inspired DataFrame library that puts model calls inside the query model, with rate limits configured per model and a caching engine underneath. The architecture is specific and the examples on the page cannot be run as printed.
Who is it for?
The idea here is worth taking seriously: a semantic operator with a declared schema is a different thing from a function call you sprinkle through a script, because the engine can then batch the calls, cache the answers, count the tokens and explain the plan.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Every code sample on the page ends inside a call

There are three code blocks in the visible text and none of them closes. The sixty-second example defines a Pydantic model with three described fields, starts a session with an app name, and configures one language model, and then the block ends on a trailing comma inside an unclosed parenthesis:

python
session = fc.Session.get_or_create(
    fc.SessionConfig(
        app_name="quickstart",
        semantic=fc.SemanticConfig(
            language_models={
                "mini": fc.OpenAILanguageModel(model_name="gpt-4o-mini", rpm=500, tpm=200_000)
            },
        ),

The eval triage example ends mid-word in the same place, and the semantic join example ends mid-word too. So the part every reader needs, the extract call and the query itself, is the part that is not on the page. The one line that does survive in the second example is a schema, three fields with descriptions and a category restricted to five literal values, which is the clearest statement of the library's central bet: you declare the shape of the answer and the engine fills typed columns rather than returning prose you have to parse.

Rate limits are part of the model configuration

The one configuration line that survives in full is the most informative thing on the page. A model is declared with a name and two limits: 500 requests per minute and 200 thousand tokens per minute. Those two numbers are the whole rate-limiting story, and they are per model rather than global, which is what makes a multi-model pipeline possible. The surrounding prose says the query engine handles automatic batching, rate limiting, retries, token and cost accounting, and response caching. That combination is the actual product: not the operators, which are a thin layer, but the execution engine that batches calls to a provider's limits, caches repeated answers and can tell you what a query cost in tokens.

The dependency set is pinned to a window one version wide

The runtime dependencies say what the engine is built on: a columnar database with a per-interpreter version split, a dataframe library with a narrow band capped below its next minor, a columnar array library, numpy split per interpreter again, a tokenizer library, a SQL parsing and transpilation library bounded across two majors, the OpenAI client, serialization helpers, a templating engine, compression, a schema-to-model converter, and the AWS SDK. The columnar array library is the tightest constraint in the file, allowed at exactly one patch version. The pair of that with the newest interpreter in the classifier list, which the library claims to support, is the combination that turns an upgrade into a resolution failure rather than a deprecation warning.

The wheel ships a skill, an agent file and a linter for writing fenic

The task runner contains one recipe with a comment that explains a design decision worth noticing: it mirrors the agent assets into the package so that installing from the index ships them, and it has to run before a wheel is built. The mirrored assets are an agent skills directory, an agent instructions file and editor rules. The page adds two commands to the same story: one installs the skill for the coding assistants, and one lints fenic code. So the distribution includes both documentation for an agent and a checker for what the agent wrote, which is a more considered answer to agent-written code than a prompt file.

Sessions are looked up by name, and a cloud tier appears only in the build

The examples never construct a session; they ask for one by an application name, which means the configuration is cached somewhere outside the object you are writing. The page says models are configured once on a session and the pipeline is built lazily. The cloud side is stranger, because it exists only in the build configuration: the task runner has a recipe that installs an extra group named for cloud, a test recipe that runs tests marked for cloud, and help text that says the default local test targets run without those cloud dependencies. The homepage is a product site. None of the visible prose explains what the cloud tier does, what it costs, or what it can do that a local session cannot.

The test matrix documents lowest and highest direct versions

The help text inside the task runner is unusually honest about how the project tests itself. It offers four ways to run the cloud tests: an ordinary sync, a variant that skips the sync entirely, one that resolves to the lowest permitted direct versions, and one that upgrades to the highest. That is a real practice for a library with pins this narrow, and it is the answer to the fragility of the dependency window. The help text also shows its own shell conditionals as examples, which means the comparisons printed in the documentation are constants that evaluate the same way every time.

A pipeline can be published as a tool an agent can call

The reuse argument closes in one line: because the work is expressed as typed operators, it can be promoted into a named table, a view, or a tool exposed over a protocol an agent can call, and there is a worked example directory for exactly that server. The inspection claims are specific too, with row-level lineage back to the source record, a plan explanation method, and per-query cost and token figures, and the eval example is written to be rerun against the next model version to catch regressions. What the page does not do is quantify any of it: there is a benchmarks directory in the repository and no numbers anywhere in the visible text, and the thirteen worked example directories are named for their shapes rather than described.

Editorial conclusion

The idea here is worth taking seriously: a semantic operator with a declared schema is a different thing from a function call you sprinkle through a script, because the engine can then batch the calls, cache the answers, count the tokens and explain the plan. The per-model rate limits are the part that shows this is meant for real pipelines rather than a demo, and the claim that a pipeline can be promoted into a named table, a view or a tool another agent can call closes a loop that most prompt libraries leave open. Two things to check first. Every code sample on the page is cut off inside a constructor, so the configuration block you need to write the first query is exactly the part that is missing, and you will be reading the site for it. And the dependency set is tightly pinned in places, down to a single permitted version of the columnar library, which means an interpreter upgrade can break the install rather than degrade it. Before adopting it, write one small pipeline against the documentation site, confirm the rate-limit figures suit your quota, and decide whether the cloud tier is something you want in the picture at all.

Frequently asked questions

What is fenic?

An Apache-2.0 Python DataFrame library for semantic data work. You write the PySpark or SQL style operations you already know, select, filter, join, group by and aggregate, alongside semantic operators such as extract, classify, summarize, embed and a semantic join that call language models as part of the query. It requires Python 3.10 or newer and is published on PyPI. It is not the finite element package of a similar name.

How do I install fenic?

With a single pip install. Model access then needs a provider key in the environment, and the page names five variables, one each for OpenAI, Anthropic, Google, Cohere and OpenRouter. Worth knowing before you start: all three code samples on the page stop inside a constructor, so the session configuration block is incomplete and you will need the site for the rest of the first query.

What does fenic do that a pandas script with model calls does not?

According to its own comparison table: typed columns validated at plan time from a declared schema instead of regex and one-off prompts, a lazy plan you can explain and rerun, row-level lineage plus per-query cost and token figures instead of scrolling a transcript, promotion of a result into a table, a view or a tool another agent can call, and one pipeline that humans and agents both read and run.

How does fenic handle model rate limits and cost?

Per model, in the session configuration: the example sets 500 requests per minute and 200 thousand tokens per minute on a single model. The page says the query engine then handles automatic batching, rate limiting, retries, token and cost accounting and response caching, and that each query can report what it cost.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. typedef-ai/fenic on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/typedef-ai-fenic.svg)](https://hysenlabs.com/projects/typedef-ai-fenic)