Connect a Real LLM to Lucifer: Claude or Any Model via Cloudflare AI Gateway

Cover Image for Connect a Real LLM to Lucifer: Claude or Any Model via Cloudflare AI Gateway
AI & Machine Learning5 min read

Building Lucifer: an open-source AI company you can watch · ⭐ GitHub

🚀 Start here: 1. Meet Lucifer · 2. Why I built it · 3. Architecture

📖 Use it: 4. Getting started · 5. Connect an LLM · 6. Office tour

🛠 Build the engine: 7. Org chart in YAML · 8. Real delegation · 9. Sandboxed tools · 10. Simulation brain

🎨 Build the office: 11. 3D office with R3F · 12. WebSocket + zustand · 13. Visualizing workflow

🧭 What's next: 14. Roadmap · 15. Contributing

The simulation brain is great for exploring Lucifer, but its deliverables are placeholders. To get real PRDs, architectures and marketing plans, connect an LLM. There are two options:

  • Anthropic Claude, natively, with a model and an effort level per employee.
  • Cloudflare AI Gateway, which puts DeepSeek, OpenAI, Gemini, Workers AI or anything else the gateway supports behind one endpoint.

Both are configured in lucifer-engine/.env. Copy .env.example to .env, choose one option, and restart the engine. The office top bar then shows the model that is running instead of Simulation.

⚠️ Real agents spend real tokens. One goal given to the CEO can turn into ten or more work sessions. Start with a small task assigned directly to one employee before you give the CEO a big goal.

How the engine picks a brain

VariableDefault
LUCIFER_BRAINautoauto, crew or sim. auto picks crew when the selected LLM has a key
LUCIFER_LLMautoanthropic or gateway. Defaults to gateway when any CF_AIG_* variable is set
LUCIFER_MODELOne model for every employee, overriding the org chart. Required for gateway

So in practice, setting the keys for one provider is enough.

Option 1: Anthropic Claude

# lucifer-engine/.env
ANTHROPIC_API_KEY=sk-ant-...

That's it. Each employee uses the model and effort from the org chart. In the default company, everyone runs claude-opus-5-5, the CEO and the CTO at effort: high (they plan and review), and everyone else at medium.

You can change that per employee in companies/lucifer-corp.yaml:

defaults:
  model: claude-opus-5-5
  effort: medium

employees:
  - id: lucifer
    title: CEO
    effort: high          # decides and merges: worth the extra thinking
  - id: belial
    title: Content Writer
    model: claude-sonnet-5-5
    effort: low           # short social posts don't need deep reasoning

effort is one of low, medium, high, xhigh or max. It is the cheapest dial you have. Lower effort means fewer thinking tokens and faster turns.

What the engine adds on top of CrewAI

CrewAI's native Anthropic provider doesn't send every parameter Lucifer uses yet, so the engine extends it as LuciferAnthropic:

class LuciferAnthropic(AnthropicCompletion):
    effort: Effort | None = None
    fallbacks: bool = False

    def _prepare_completion_params(self, *args, **kwargs):
        params = super()._prepare_completion_params(*args, **kwargs)
        extra_body = {}
        if self.effort:
            extra_body["output_config"] = {"effort": self.effort}
        if self.fallbacks:
            extra_body["fallbacks"] = "default"
            params["extra_headers"] = {"anthropic-beta": FALLBACK_BETA}
        if extra_body:
            params["extra_body"] = extra_body
        return params
  • output_config.effort carries each employee's effort level.
  • fallbacks: "default" means a request the safety classifier declines is retried on a fallback model, instead of failing the task. Turn it off with LUCIFER_FALLBACKS=0.

CrewAI adds prompt caching on its own. Lucifer helps it along: an agent's backstory depends only on the company and the agent's position, never on the task, so the long prefix of every request is the same from one work session to the next and can be cached.

Note: CrewAI's provider reads ANTHROPIC_API_KEY only. It does not use an ant auth login profile.

Option 2: Cloudflare AI Gateway

Cloudflare AI Gateway gives you one OpenAI-compatible endpoint in front of many providers, with caching, rate limits, logs and fallbacks managed on Cloudflare. Lucifer calls its /compat/chat/completions endpoint.

The simplest setup stores your provider key on the gateway (BYOK), so the engine only needs a Cloudflare token:

# lucifer-engine/.env
CF_AIG_ACCOUNT_ID=<account id>
CF_AIG_GATEWAY_ID=<gateway id>
CF_AIG_TOKEN=<Cloudflare API token>
LUCIFER_MODEL=deepseek/deepseek-chat

LUCIFER_MODEL is provider/model, for example deepseek/deepseek-chat or openai/gpt-5. It can also be dynamic/<route> to let a dynamic route on Cloudflare choose the model, which is how you configure retries and fallbacks across providers.

The demo video for live work in the Lucifer README was recorded exactly like this, with DeepSeek.

The variables you might need

VariableWhen
CF_AIG_BYOK_ALIASYour stored provider key is not named default. Without it the gateway answers no BYOK credential named 'default'.
CF_AIG_PROVIDER_KEYYou don't store the provider key on Cloudflare. The token then goes in the cf-aig-authorization header.
CF_AIG_BASE_URLYou use a custom domain. Overrides the whole /compat URL.
LUCIFER_STRICT_TOOLS1 sends tools with strict: true. Use it with OpenAI models only.

Why strict tools are off by default

CrewAI always sends tool definitions with strict: true, which is an OpenAI mode. DeepSeek and many other providers reject requests that use it. The gateway brain removes the flag unless you opt in:

class GatewayCompletion(OpenAICompletion):
    strict_tools: bool = False

    def _convert_tools_for_interference(self, tools):
        converted = super()._convert_tools_for_interference(tools)
        if not self.strict_tools:
            for tool in converted:
                tool["function"].pop("strict", None)
        return converted

Through the gateway, the Claude-specific effort and server-side fallbacks are not sent.

Keeping the bill under control

A few habits that keep costs predictable:

  1. Start small and direct. Assign a single deliverable to one employee, for example "Write 3 social posts about our launch, save them to content/launch-posts.md" for Belial. One work session, a few tool calls.
  2. Write a clear brief. Ask for named files and a specific scope. A vague goal makes the CEO delegate broadly, and every delegation is another session.
  3. Tune effort per role. Planning roles benefit from high. Writers and specialists often do fine at medium or low.
  4. Limit concurrency. LUCIFER_MAX_CONCURRENT (default 4) caps how many agents work at once. It won't reduce the total, but it slows the spend down and keeps it observable.
  5. Watch the stats. Click an angel and its drawer shows the tokens it has used so far, so you can see who is expensive.
  6. Cancel freely. Cancelling a task in its drawer cancels all its open subtasks, and running sessions stop at their next step.
  7. Use the simulation brain for UI work. Set LUCIFER_BRAIN=sim while you develop, even with keys in .env.

Language

You don't configure a language. The engine detects it from your request (Vietnamese, Japanese, Korean, Chinese, Thai and English are recognized) and passes it down to every subtask. Each brief tells the agent to write files, updates and summaries in that language. Write the request in Vietnamese and the whole company answers in Vietnamese. To force a language, pass "language": "Vietnamese" to POST /api/tasks.

Next

The code is on GitHub at siri2moon/lucifer.


Lucifer is open source under the MIT license. Clone it, run it for free with the simulation brain, and ⭐ star it if you'd like to follow along: github.com/siri2moon/lucifer.

Next in the series: A Tour of the Lucifer Office: Missions, Work Links, Follow Camera and Break Time.