DAILY NEWS

Stay Ahead, Stay Informed – Every Day

Advertisement
Understanding Apache Airflow DAGs: Structure, Communication, and Deployment



Apache Airflow has become one of the most widely used workflow orchestration platforms for building, scheduling, and monitoring data pipelines. At the heart of Airflow lies the Directed Acyclic Graph (DAG), a structure that defines how tasks are organized and executed. Understanding DAGs is essential for anyone working with data engineering, ETL pipelines, or workflow automation.

What is a DAG?A Directed Acyclic Graph (DAG) is a collection of tasks organized in a way that defines dependencies and execution order.

Directed- means tasks have a specific direction of execution.
Acyclic- means there are no loops; a task cannot eventually depend on itself.
Graph- represents the relationship between tasks.

Basic DAG StructureA typical Airflow DAG consists of:

DAG definition
Tasks (Operators or TaskFlow functions)
Dependencies

from airflow.sdk import dag, task
from datetime import datetime
@dag(
start_date=datetime(2026, 1, 1),
schedule=”@daily”,
catchup=False
)
def sample_dag():
@task def extract():
return “data”
@task def transform(data):
return data.upper()
@task def load(data):
print(data)
load(transform(extract()))
sample_dag()

Enter fullscreen mode

Exit fullscreen mode

This DAG follows a simple Extract → Transform → Load pattern.

Task Communication with XCom

Tasks in Airflow are isolated from one another. To share information between tasks, Airflow provides Cross-Communication (XCom).

XCom allows tasks to push and pull small pieces of data.

Deploying DAGs with SCP

In many production environments, Airflow runs on a remote Linux server. Instead of manually recreating DAG files, engineers often use Secure Copy Protocol (SCP) to transfer DAGs.

scp gas_prices_dag.py user@server:/home/user/airflow/dags/

Enter fullscreen mode

Exit fullscreen mode

This command securely copies the DAG file to the server’s DAG directory.

SCP is especially useful when deploying updated pipelines from a development machine to a production Airflow environment.

Running Airflow Services with nohup

Airflow components such as the scheduler and webserver need to remain running even after a terminal session closes.

The nohup command helps achieve this.

nohup airflow standalone &

Enter fullscreen mode

Exit fullscreen mode

This starts the scheduler in the background and prevents it from stopping when the terminal closes.The output is redirected to log files for troubleshooting.

Managing Airflow with systemd

For production environments, systemd is the preferred way to manage Airflow services.

A systemd service can automatically:

Start Airflow after system boot
Restart failed services
Manage logs
Monitor service health

Monitoring and Troubleshooting DAGs

Airflow provides a web interface where users can:

Trigger DAG runs
Monitor task execution
View task logs
Retry failed tasks
Inspect XCom values

ConclusionApache Airflow DAGs provide a powerful way to orchestrate complex workflows and data pipelines. By understanding DAG structure, task dependencies, XCom communication, and deployment techniques such as SCP, nohup, and systemd, data engineers can build reliable and maintainable ETL systems. Whether running a simple daily pipeline or a large-scale production workflow, mastering DAGs is the foundation of effective workflow orchestration with Apache Airflow.



Source link

Use a flat-priced, auto-routing LLM API in Aider or Cline — one npx command



Coding assistants like Aider, Cline, and Continue all speak the OpenAI wire protocol — point them at a base_url, give them an API key, done. That makes swapping in a different LLM backend trivial… if that backend uses Authorization: Bearer.

The flat-priced, auto-routing API I’d been using doesn’t. It’s distributed through RapidAPI, which authenticates with an X-RapidAPI-Key header instead of Bearer. So I couldn’t just drop it into Aider. The fix turned out to be ~120 lines, so I open-sourced it.

modelis-openai

A zero-dependency local proxy (MIT, Node 18+). It listens on 127.0.0.1, speaks plain OpenAI, rewrites the auth header, and forwards to the upstream gateway. Streaming (stream: true) is piped straight through, so token-by-token output works exactly as with the OpenAI API.

your tool ──OpenAI(Bearer)──▶ modelis-openai (localhost) ──X-RapidAPI-Key──▶ upstream ──▶ best model

Enter fullscreen mode

Exit fullscreen mode

Quickstart

npx modelis-openai

Enter fullscreen mode

Exit fullscreen mode

Then point any OpenAI-compatible tool at it:

Setting
Value

Base URL
http://127.0.0.1:8787/v1

API key
your RapidAPI key

Model
modelis-auto

Drop it into your tool

Aider

export OPENAI_API_BASE=http://127.0.0.1:8787/v1
export OPENAI_API_KEY=
aider –model openai/modelis-auto

Enter fullscreen mode

Exit fullscreen mode

Cline / Roo Code — API Provider OpenAI Compatible, Base URL http://127.0.0.1:8787/v1, Model ID modelis-auto.

Continue (~/.continue/config.yaml)

models:
– name: Modelis
provider: openai
model: modelis-auto
apiBase: http://127.0.0.1:8787/v1
apiKey:

Enter fullscreen mode

Exit fullscreen mode

Any OpenAI SDK

from openai import OpenAI
client = OpenAI(base_url=”http://127.0.0.1:8787/v1″, api_key=””)
print(client.chat.completions.create(
model=”modelis-auto”,
messages=({“role”: “user”, “content”: “Hello”}),
).choices(0).message.content)

Enter fullscreen mode

Exit fullscreen mode

How it works

Reads the key from Authorization: Bearer (or MODELIS_RAPIDAPI_KEY).
Rewrites the request model to modelis-auto (configurable).
Forwards to the RapidAPI gateway with X-RapidAPI-Key / X-RapidAPI-Host.
Relays the response — including SSE streams and rate-limit headers — unchanged.

It also answers GET /v1/models and GET /health so tools that probe on startup don’t choke.

Honest notes

It routes to a paid API (there’s a free tier to start). The point of the proxy is to remove the integration friction, not to give anything away.

Cursor isn’t supported — it sends requests from its own servers, so a localhost endpoint can’t be reached. This is for tools that call the API from your machine.

Links

If you try it in a tool I didn’t list, I’d love to hear how it goes.



Source link

The CTO Playbook for AI Agent Data Analysis on a Budget



So here’s what happened: the CTO Playbook for AI Agent Data Analysis on a Budget

Six months ago my engineering team was burning roughly $14,000 a month on a single AI agent data pipeline. The model was great. The latency was fine. The output quality was honestly impressive. But the bill was eating our runway, and I had to make a call that would have felt absurd a year earlier: rip out a perfectly working stack and rebuild it from scratch.

This is the story of how I did it, what I learned shipping AI agent data analysis at scale, and why I now treat model choice the same way I treat database choice — as a strategic decision, not a default.

The Wake-Up Call

We had built our analytics agent on GPT-4o. It is a phenomenal model. I will not pretend otherwise. But the moment we crossed about 8 million tokens per day of production traffic, the math stopped working. At $2.50 per million input tokens and $10.00 per million output tokens, every new customer we onboarded was a net loss on infrastructure for the first three months.

I remember staring at the dashboard one Tuesday morning. Throughput was fine. The model was hitting the benchmarks we cared about. Our NPS was climbing. And yet finance was flagging the line item every week. That is the moment every startup CTO dreads: when the thing that is working is also the thing that is going to kill you if you do not change it.

So I started asking the questions I should have asked on day one. Which models are actually production-ready for our workload? What is the real cost gap between flagship models and the new generation of leaner ones? And critically, can I switch providers without rewriting my entire application?

That last question is the one nobody talks about. Vendor lock-in in the LLM space is real, and it is sneakier than cloud lock-in. When your prompt engineering, your evaluation harness, your retry logic, and your observability all assume one provider’s API shape, switching costs are not just financial — they are engineering hours you do not have.

The Cost Numbers That Made Me Switch

Once I started looking at the market seriously, the gap was jaw-dropping. Global API currently lists 184 models, with prices ranging from $0.01 to $3.50 per million tokens depending on tier. That spread is not academic. For an analytics agent, where input tokens dominate (because you are shoving tables, schemas, and prior context into every prompt), the input price is what actually moves your P&L.

Here is the comparison I built for my board deck:

Model
Input ($/M)
Output ($/M)
Context

DeepSeek V4 Flash
0.27
1.10
128K

DeepSeek V4 Pro
0.55
2.20
200K

Qwen3-32B
0.30
1.20
32K

GLM-4 Plus
0.20
0.80
128K

GPT-4o
2.50
10.00
128K

Look at GLM-4 Plus. $0.20 input, $0.80 output, 128K context window. For a large slice of our agent traffic — the follow-up questions, the structured summarization calls, the routing layer — the quality delta against GPT-4o was inside the noise floor of our human eval set. The cost delta was 12x.

That is when I knew. We were not paying for quality. We were paying for the logo on the box.

The Architecture I Actually Shipped

I am going to walk you through the production-ready setup we landed on, because I think it is the right shape for almost any team running AI agent data analysis at scale.

The core insight is that “AI agent data analysis” is not one workload. It is at least four:

Routing and intent classification — tiny prompts, high volume, must be cheap and fast.

Schema and tool selection — moderate context, structural reasoning.

Heavy analytical reasoning — the flagship call, where quality actually matters.

Verification and self-critique — another model call, where consistency matters more than peak brilliance.

Each of those workloads has a different price-quality sweet spot. Treating them as one homogeneous workload is how teams end up with $14,000 monthly bills for what should be a $3,000 service.

My routing logic now looks at the incoming query, classifies it (using GLM-4 Plus, which is dirt cheap), and then dispatches to one of three model tiers. The flagship calls — maybe 15% of total volume — still hit a top-tier model. The other 85% lands on leaner, faster, dramatically cheaper endpoints.

The result: a 40-65% cost reduction against our previous all-GPT-4o stack, with our internal quality benchmarks moving by less than 2 percentage points. That is the kind of ROI your CFO actually notices.

The Code

Here is the base client setup we use everywhere. I am showing the Python version because that is what our data team writes, but the same shape works in Node and Go.

import os
from openai import OpenAI

# when we swap providers — the entire point of routing through
# a unified API surface.
client = OpenAI(
base_url=”https://global-apis.com/v1″,
api_key=os.environ(“GLOBAL_API_KEY”),
)

def classify_query(user_query: str) -> str:
“””Cheap intent classification. GLM-4 Plus is plenty for this.”””
response = client.chat.completions.create(
model=”z-ai/glm-4-plus”,
messages=(
{
“role”: “system”,
“content”: “Classify the user’s analytics query as: simple, structured, or deep. Reply with one word only.”,
},
{“role”: “user”, “content”: user_query},
),
temperature=0.0,
max_tokens=4,
)
return response.choices(0).message.content.strip().lower()

def run_agent(user_query: str, context: str) -> str:
“””Dispatch to the right model tier based on query complexity.”””
tier = classify_query(user_query)

if tier == “deep”:
# Flagship tier — only for the hard stuff.
model = “deepseek-ai/DeepSeek-V4-Pro”
elif tier == “structured”:
# Mid tier — schema reasoning, tool calls.
model = “deepseek-ai/DeepSeek-V4-Flash”
else:
# Default tier — follow-ups, summarization, simple Q&A.
model = “Qwen3-32B”

response = client.chat.completions.create(
model=model,
messages=(
{“role”: “system”, “content”: “You are a senior data analyst. Reason step by step.”},
{“role”: “user”, “content”: f”Context:\n{context}\n\nQuestion: {user_query}”},
),
temperature=0.2,
)
return response.choices(0).message.content

Enter fullscreen mode

Exit fullscreen mode

Notice the base_url. That single line is the reason I am not locked into any one provider. If a better-priced model drops next quarter, or if a provider has a regional outage, I change the model string and move on. My application code, my prompt library, my eval harness — none of it changes. That is vendor lock-in avoidance as a feature, not as an afterthought.

For streaming responses on the deep tier, here is a second snippet that has saved us a lot of perceived latency complaints:

def stream_agent(user_query: str, context: str):
“””Stream the flagship tier for time-to-first-token gains.”””
response = client.chat.completions.create(
model=”deepseek-ai/DeepSeek-V4-Pro”,
messages=(
{“role”: “system”, “content”: “You are a senior data analyst.”},
{“role”: “user”, “content”: f”Context:\n{context}\n\nQuestion: {user_query}”},
),
stream=True,
temperature=0.2,
)
for chunk in response:
delta = chunk.choices(0).delta.content
if delta:
yield delta

Enter fullscreen mode

Exit fullscreen mode

Streaming shaved roughly 800ms off perceived response time on our longest-tail queries. At scale, that is the difference between a user thinking “this feels fast” and “this feels slow.”

What Actually Broke (And What I Learned)

I would be lying if I said the migration was clean. A few things bit us, and I want to be honest about them because the marketing material never is.

Tokenization differences. When you swap models, token counts do not transfer 1:1. The same English prompt can be 10-15% more tokens on one model than another. We had to rebuild our cost forecasting model from scratch. I am embarrassed how long I assumed tokenization was standard.

Latency variance. The 1.2s average latency number is real, but averages lie. We saw p99 latency spike on two of the cheaper models during US evening hours. We solved it with a simple fallback chain: if a call does not return inside 4 seconds, retry once on the next tier up. Costs us a few percent. Saves us a lot of angry customers.

Quality variance on edge cases. Our flagship model caught a subtle statistical error in about 95% of cases. The mid-tier model caught it in about 82%. That sounds small, but in a data analysis product, a silent miscalculation is a brand-destroyer. We added a verification call (using a different model family to avoid correlated errors) on any answer that involves numbers. The 84.6% average benchmark score we see is the blended result across all tiers.

Cache behavior. I cannot stress this enough: cache aggressively. We saw a 40% hit rate on our analysis queries within the first week, because analysts ask the same questions in slightly different ways. That 40% is pure margin. If you are not caching at the prompt-similarity level, you are leaving money on the table.

The Vendor Lock-In Question

This deserves its own section because it is the part of the conversation I think most CTOs avoid.

When you build on a single provider’s API, you are not just buying tokens. You are buying into their SDK conventions, their rate limit semantics, their error envelope, their deprecation policy, and their pricing roadmap. The moment any of those change in a way you do not like, you are stuck. And in the current LLM market, pricing has been dropping roughly 10x per year for equivalent capability. Locking in at last year’s prices is a real cost.

Routing through a unified API surface like Global API does not magically fix this, but it shifts the dependency from “the model vendor” to “the routing layer.” That is a much better place to be, because the routing layer has an economic incentive to keep you portable. Your model vendor does not.

We also run a quarterly exercise I call the “swap drill.” I take one of our production endpoints, switch it to a different model for a week, and measure the quality and cost delta. It is two engineer-days of work. It keeps us honest, and it means that if any provider raises prices or has a reliability incident, we are not scrambling — we are executing a playbook we have already rehearsed.



Source link