Building a “Soft Sensor” for Cement Kilns: Predicting Control Levers with Python

In the cement industry, the “Ustad” (Master Operator) knows that a kiln is a living beast. When the lab results for the Raw Meal come in, the operator has to balance the “Four Pillars” of control to ensure the clinker is high quality and the kiln remains stable.

Wait too long to adjust, and you risk a “snowball” in the kiln or high free lime. This is where Machine Learning comes in. In this article, we will build a Soft Sensor using Python to predict the four critical control levers based on raw meal chemistry.

The Four Pillars of Kiln Control
To keep a kiln in a steady state, we must manage four interconnected variables:

Kiln RPM: Controls the material residence time.

ID Fan Setting: Manages the draft and oxygen (the kiln’s lungs).

Feed Rate: The amount of raw material entering the system.

Fuel Adjustment: The thermal energy required for the sintering zone.

The Architecture: Multi-Output Regression
Because these four variables are physically dependent on each other (e.g., if you increase Feed, you usually must increase Fuel and RPM), we shouldn’t predict them in isolation. We will use a Multi-Output Regressor with XGBoost.

Step 1: The Setup
Python
import pandas as pd
import numpy as np
from xgboost import XGBRegressor
from sklearn.multioutput import MultiOutputRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_absolute_error

1. Load your dataset

Features: LSF (Lime Saturation), SM (Silica Modulus), AM (Alumina Modulus), Moisture

Targets: RPM, ID Fan, Feed Rate, Fuel

df = pd.read_csv(‘kiln_process_data.csv’)

X = df[[‘LSF’, ‘SM’, ‘AM’, ‘Moisture_Pct’]]
y = df[[‘Kiln_RPM’, ‘ID_Fan_Pct’, ‘Feed_Rate_TPH’, ‘Fuel_TPH’]]

2. Train/Test Split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

3. Scaling (Important for industrial data ranges)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
Step 2: Training the “Soft Sensor”
We use the MultiOutputRegressor wrapper. This allows one model to handle all four targets while maintaining the statistical relationships between them.

Python

Initialize the base XGBoost model

base_model = XGBRegressor(
n_estimators=500,
learning_rate=0.05,
max_depth=6,
subsample=0.8,
colsample_bytree=0.8
)

Wrap it for multi-output

soft_sensor = MultiOutputRegressor(base_model)

Fit the model to the kiln data

soft_sensor.fit(X_train_scaled, y_train)

Predictions

predictions = soft_sensor.predict(X_test_scaled)
Step 3: Evaluation & “Ustad” Logic
In the plant, accuracy isn’t just a percentage; it’s about staying within mechanical limits. We evaluate each lever individually:

Python
targets = [‘Kiln_RPM’, ‘ID_Fan_Pct’, ‘Feed_Rate_TPH’, ‘Fuel_TPH’]
for i, col in enumerate(targets):
mae = mean_absolute_error(y_test.iloc[:, i], predictions[:, i])
print(f”Mean Absolute Error for {col}: {mae:.4f}”)
Safety Guardrails (The “Control” Logic)
Machine Learning models can sometimes suggest “impossible” values. In production, we wrap the model in a clipping function to respect the physical limits taught by the masters.

Python
def get_operational_settings(raw_meal_inputs):
# Scale inputs
scaled_input = scaler.transform(raw_meal_inputs)
raw_pred = soft_sensor.predict(scaled_input)[0]

# Apply Safety Constraints
safe_settings = {
    "Kiln_RPM": np.clip(raw_pred[0], 1.5, 4.2),    # Max RPM 4.2
    "ID_Fan": np.clip(raw_pred[1], 65, 95),       # Draft range
    "Feed_Rate": np.clip(raw_pred[2], 200, 450),  # TPH range
    "Fuel": np.clip(raw_pred[3], 15, 30)          # Burner capacity
}
return safe_settings

Why This Matters
Reduced Variability: No matter which operator is on shift, the model provides a consistent “baseline” adjustment based on the chemistry.

Energy Efficiency: Precision fuel and ID fan control directly reduce the heat consumption per kilogram of clinker.

Proactive Control: You move from reacting to lab results to predicting the necessary changes.

Conclusion
Building a Soft Sensor for a cement kiln isn’t just about the code; it’s about translating chemical moduli into mechanical action. By using Python and Multi-Output Regression, we can digitize the “intuition” of the best operators and create a more stable, efficient plant.

Are you working on Industrial AI? Let’s discuss in the comments!

Python #DataScience #Manufacturing #IndustrialIoT #CementIndustry

I Built an AI Agent That Can Write Its Own Tools When It Gets Stuck

Most AI agents are only as capable as the tool list they shipped with.

They can browse, click, read files, maybe run some shell commands, maybe call a few prebuilt functions. But once they hit a task their built-in actions don’t cover, they usually stall out. At that point, you either have to add the missing functionality yourself, wire in some external skill system, or accept that the agent has reached the edge of its world.

That always felt like a major limitation to me.

So I built GrimmBot, an open source AI agent that can do something I find much more interesting: when it runs into a capability gap, it can generate a new Python tool for itself, test it, and add it to its own toolkit for future use.

That’s the headline feature, but it isn’t the whole story. GrimmBot also runs in a sandboxed Debian Docker environment, uses Chromium as its default browser, has persistent memory, supports scheduling, and can watch webpages or screen regions for long periods without constantly burning API tokens. The bigger goal was to build an agent that doesn’t just act — it can wait, remember, schedule work, and adapt when its built-in tools are no longer enough.

Repo: https://github.com/grimm67123/grimmbot

Demo videos are in the repo.

The problem with static agents

A lot of current AI agents are impressive right up until the moment they need one thing they don’t already know how to do.

That could be something small and annoying, like:

  • parsing a weird file format
  • extracting data from a custom log structure
  • handling some specific transformation step
  • navigating an unusual workflow
  • bridging two built-in capabilities with custom logic

The model may understand exactly what needs to happen, but if the environment doesn’t expose the right function, the agent is stuck.

That creates a strange mismatch. The “intelligence” of the system can often see the path forward, but the actual action layer is boxed in by a fixed menu of tools.

I wanted to experiment with a different approach: what if the agent could extend that menu itself?

What GrimmBot does differently

GrimmBot has a capability for autonomous tool generation.

In practical terms, that means if it encounters a task its current toolset can’t handle, it can create a new Python tool, integrate it into its available tools, and use it again later if needed.

So instead of treating the shipped toolset as a hard boundary, GrimmBot can treat it as a starting point.

That doesn’t mean the agent is rewriting itself in some dramatic sci-fi sense. The point is much more practical than that. It means the system has a path for adaptation when it hits a task-specific wall.

To me, that makes the agent feel much less brittle.

Why I think this matters

The current pattern in a lot of agent systems is:

  1. define a set of built-in tools
  2. let the model choose among them
  3. fail when none of them fit

That works fine for predictable workflows, but the real world is full of edge cases and highly specific requirements.

If an agent is going to be genuinely useful in open-ended tasks, I think it needs some ability to adapt when the prebuilt path isn’t enough. Otherwise it’s always one missing function away from dead-ending.

That’s what interested me most about autonomous tool generation: not the “wow” factor, but the practical reduction in brittleness.

A rigid agent can be impressive in demos.

An adaptable agent is much more interesting in real use.

The broader system around it

I didn’t want this to be just a toy experiment around generated tools. I wanted the capability to exist inside a broader agent environment.

So GrimmBot runs inside a Debian Docker container and uses Chromium as its default browser. It has a virtual desktop environment, browser control, file operations, shell access, coding-related functions, memory systems, scheduling, and human-approval pauses for sensitive actions.

That matters because tool generation by itself is not very useful if the rest of the system is too narrow.

The point isn’t just “the agent can write code.” The point is that the agent lives inside a sandboxed environment where that new code can become part of a larger workflow.

For example, a useful agent might need to:

  • browse to a page
  • inspect data
  • realize it needs a custom parser
  • generate that parser as a new tool
  • save the result
  • remember the outcome
  • schedule a follow-up
  • monitor for the next change

That is much more interesting to me than just proving a model can emit Python.

Zero-token monitoring was another major design goal

While autonomous tool generation is the most conceptually interesting part of GrimmBot to me, another major problem I wanted to solve was monitoring.

A lot of AI agents burn tokens while they wait.

If you ask them to watch a webpage, wait for text to appear, keep an eye on a status page, or monitor a region of the screen for a change, many systems keep involving the LLM over and over while nothing is happening.

That feels wasteful.

Waiting is not reasoning.

So GrimmBot includes monitoring tools that can run local loops against the DOM or screen regions without continuously waking the model. The LLM decides what to watch for, invokes the right monitoring tool with the needed arguments, and then sleeps while the local loop does the boring part. It only wakes up when the trigger condition is actually met.

I consider that an important part of the same design philosophy.

An agent should not use the model for everything just because the model is available.

Persistent memory and scheduling

I also wanted GrimmBot to be useful beyond one-shot tasks.

In real workflows, agents often need to:

  • remember context across sessions
  • store useful facts or task state
  • revisit something later
  • run at intervals
  • continue work after a delay

So GrimmBot includes persistent memory and scheduling features as part of the broader system.

That way the agent is not forced to behave like every task starts from zero and ends immediately. It can maintain continuity better over time.

That matters even more once you combine it with monitoring and generated tools.

An agent that can:

  • remember
  • wait
  • schedule
  • adapt

is much closer to being operationally useful than one that can only act in the moment.

Why I built it this way

The common thread across all of this is that I wanted to reduce brittleness.

Static toolsets are brittle.

Constant LLM polling is brittle and wasteful.

No memory is brittle.

No scheduling is brittle.

A sandboxed environment with browser access, persistent context, monitoring, and the ability to generate task-specific tools felt like a more interesting direction.

I’m not claiming this magically solves every problem with agents. But I do think it points toward a model of agents that is more grounded in real workflows and less dependent on “hope the built-ins are enough.”

We Traced One Query Through Perplexity’s Entire Stack in Cohort – Here’s What Actually Happens in 3 Seconds

It was about 90 minutes into the session. We’d just finished building a RAG pipeline from scratch in Python the kind where you stare at FAISS indices and embeddings and wonder if you’ll ever actually deploy this in prod.

The instructor stopped scrolling through code and looked up.

“Alright,” he said. “Let’s stop pretending we’re building search. Let’s trace one live query through Perplexity. See what actually happens in the 3 seconds between you hitting enter and reading the answer.”

The room got quiet. Someone typed the question.

First, the Simple RAG Pattern (So We Have a Baseline)

If you’ve built any RAG system, you know the dance:

  1. Ingest — chunk documents, embed them, store in a vector DB
  2. Retrieve — embed the query, find the closest chunks
  3. Augment — inject those chunks into a prompt
  4. Generate — LLM answers, grounded in your docs

That’s the 40-line Python version. Clean. Predictable. Works great when your docs are a handful of policy PDFs.

But Perplexity isn’t doing that with 10 PDFs. It’s doing it with the entire internet, in real time, with a re-ranking step you won’t find in any beginner tutorial.

Here’s what we actually saw.

The Live Trace: One Query, Five Layers, Three Seconds

The query we used:

“What are the best practices for deploying LLMs in production?”

Not some toy question. Real. Ugly. Vague enough that a naive search would return 50 different blog posts with contradictory advice.

Layer 1 — Data Ingestion

The first thing that happens isn’t embedding. It’s crawling. Perplexity’s web crawler runs constantly, but for this query, it also fired off real-time searches to Bing and other indexes. Within milliseconds, it had 10–20 candidate web pages.

We could see the sources flash on screen: papers from Anthropic, blog posts from engineering teams at Uber and DoorDash, a surprisingly useful Hacker News thread from last week.

That last one matters: Perplexity isn’t using static training data. It’s pulling from this week.

Layer 2 — Embeddings

Now it gets messy. Each of those 10–20 pages gets chunked into paragraphs (300–500 words each). Each paragraph gets embedded. The query gets embedded.

This is the part everyone understands. But here’s where it diverges from the simple RAG tutorial:

Layer 3 — Vector Search + Re-ranking

FAISS (or whatever vector index they’re using) finds the top 20–50 chunks based on cosine similarity. That’s the cheap, fast pass.

This is the part that surprised everyone in the cohort, they run a second retrieval pass with a dedicated re-ranking model. Not the same embedding model. A separate model trained specifically to score relevance more precisely.

Why? Because vector search alone will surface things that are semantically close but practically useless. Re-ranking fixes that.

We watched as the top results shifted. A paragraph about deployment strategies from a Google engineering blog jumped from position 12 to position 3. A random forum post dropped out entirely.

Result: 5–8 highly relevant paragraphs. Not 50.

Layer 4 — Orchestration

This is where the prompt engineering happens, but not the kind you type yourself. Perplexity constructs a prompt that includes:

  • System instructions for citation formatting
  • The retrieved paragraphs (each tagged with its source URL)
  • Your original query

The citations aren’t an afterthought. They’re part of the context, tracked through the entire orchestration layer so the final answer can link back to sources.

Layer 5 — LLM Generation

Finally, the model generates. In our trace, it was GPT-4o (though Perplexity switches models depending on the query type). The output came back with inline citations, a summary of key practices, and links to the original sources.

Total elapsed time: maybe 4 seconds. It felt instant.

What Surprised Us

Two things broke our assumptions.

First: the re-ranking step.

Everyone in the room thought Perplexity was just doing vector search + an LLM. None of us expected a dedicated re-ranking model. Once we saw it, it made sense, vector search alone is too noisy for production-grade answers. But it’s not something you see in the “build your own RAG” tutorials.

Second: the citation tracking.

This isn’t just “the model cites sources.” The orchestration layer is carefully constructed so the LLM has to include citations. The retrieved chunks come with metadata that the prompt instructs the model to reference. It’s not a nice-to-have. It’s a constraint baked into the architecture.

One person in the cohort said it best: “Oh, so this is RAG where the data source is the entire internet, and the retrieval is actually good.”

The Practical Lesson for Developers in 2026

Here’s what I took away, and it’s not “go build your own Perplexity.”

Understanding these pipelines the actual layers, not just the high-level “RAG is search + generation” is now table stakes. Even if you never deploy a vector database or train a re-ranking model, you need to know:

  • Why your naive RAG prototype fails (because retrieval is noisy and you have no re-ranking)
  • Why Perplexity’s answers feel better than ChatGPT with web search (because the orchestration layer is doing 10x more work than you think)
  • Why citation tracking matters for trust, not just compliance

The product’s value isn’t in the model. It’s in the retrieval, the re-ranking, and the prompt construction. Perplexity uses the same models you have access to. What makes it work is everything before the LLM runs.

That’s the part you can’t see from the chat interface. And that’s the part worth understanding.

P.S. — If you’re curious, here’s the 5-layer breakdown we ended the session with:

Layer What Actually Happens
1. Data Ingestion Real-time web crawl + indexes, 10–20 candidate pages
2. Embeddings Chunk pages → embed chunks + query
3. Vector Search + Re-ranking FAISS-style fast retrieval → dedicated model re-ranks to top 5–8
4. Orchestration Construct prompt with citations, source tracking, system instructions
5. LLM Generation Model writes grounded answer with inline links

That’s what happens in the 3 seconds. Now you know.

Wednesday Links – Edition 2026-04-01

Java Is Fast. Your Code Might Not Be. (12 min)🐢
https://jvogel.me/posts/2026/java-is-fast-your-code-might-not-be/

JDK 26 Security Enhancements (14 min)🛡️
https://seanjmullan.org/blog/2026/03/16/jdk26

Measuring the Startup Memory Cost for Lazy Iteration Patterns in Java (5 min)💰
https://donraab.medium.com/measuring-the-startup-memory-cost-for-lazy-iteration-patterns-in-java-be24f4dd5b64

One tip for successful OpenTelemetry projects (2 min)💡
https://blog.frankel.ch/tip-opentelemetry-projects/

Static code analysis in Kotlin — tools overview (16 min)👀
https://blog.allegro.tech/2026/03/static-code-analysis-kotlin.html

Your content pipeline is lying to you, and in regulated software, that’s a serious problem

There is a category of bug that does not show up in your test suite, does not trigger an alert, and does not produce a stack trace. It looks like this: the wrong version of your content is running in production, and you have no reliable way to prove otherwise.

For most applications, this is embarrassing. For software in regulated industries (medical devices, industrial systems, certified training applications, etc.) it can be a compliance failure with real consequences.

This post is about why this happens, why the obvious fixes do not actually fix it, and what a correct architecture looks like.

The problem with treating content like database state

Most content pipelines work roughly like this: content lives somewhere editable (a CMS, a database, Notion, a spreadsheet), a build process or runtime query pulls it out, and the application delivers it to users.

The fundamental assumption baked into this model is that “current content” means “whatever is in the database right now.” That assumption is fine for a marketing website where you want changes to go live immediately. It is quietly disastrous for applications where what was delivered to a user needs to be auditable, reproducible, and tied to a specific approval event.

Consider a company building certified training software for medical device manufacturers. Their content — the training material that end users complete to be certified on a device — must reflect what was reviewed and approved by the manufacturer. If an editor makes a change in the CMS, saves it, and that change goes live immediately in the training application, you have a pipeline where:

  • There is no reliable record of what content was actually delivered to a specific user session
  • An approved state can be silently overwritten by any subsequent edit
  • Future content revisions for the next operating procedure version cannot be safely developed without risk of contaminating current production content
  • An audit asking “what exactly did this user see on this date?” cannot be answered with certainty

None of these are edge cases in regulated software. They are exactly the questions that certification and compliance processes ask.

Why the obvious solutions fall short

“We’ll just add an approval workflow to our CMS.”

While restricting the publication of content can solve the immediate issue of controlling which content reaches production, it cannot prevent that future content revisions overwrite existing published content. This makes it impossible to operate multiple exactly defined revisions in parallel, as end-users gradually switch to new procedures at their own pace.

“We’ll use database snapshots or backups.”

Snapshots are a disaster recovery mechanism, not an audit trail. They are coarse-grained, difficult to query selectively, and not designed to answer “show me exactly what field X contained for entry Y at timestamp T and who approved it.”

“We’ll version our database records.”

You can build this. It requires significant custom engineering, and you will need to think carefully about referential integrity across versions, query complexity for fetching a consistent snapshot of related content at a given version, and how to expose this to non-technical content editors in a way that does not cause confusion. Going down this path is a surefire way of spending development effort on closing down a never-ending series of edge-cases, where that effort could have been spent on further building out your core product instead.

“We’ll bake content into the application binary at build time.”

This solves the “content changed at runtime” problem but introduces a different one: the only way to update content is to rebuild and redeploy the entire application. Iteration speed becomes painful. More importantly, you still need a way to manage and audit what goes into the build — the source of truth upstream of the binary is still mutable.

What a correct architecture actually requires

The properties you need are specific and worth stating precisely:

Immutability by reference. A given version of your content, once approved, must be permanently retrievable by a stable identifier. Not “the current state of approved content” but “the exact state of content as of approval event #4471.”

Referential consistency. If your content model has relationships (e.g. a training module references a set of questions, which reference a set of answer options) fetching a specific version must return a consistent snapshot of the entire graph, not a mix of versions from different points in time.

A separation between working state and production state. Authors need to be able to work on future revisions without those changes being visible to production consumers. This is a branching problem, not a permissions problem.

An audit trail that is structural, not appended. The history of what changed, when, and as a result of what approval event should be intrinsic to the storage model, not a log table bolted on afterward.

Git already solved this problem for code

If you step back, these are exactly the properties that Git provides for source code:

  • Every commit is content-addressed and permanently immutable
  • A commit captures a consistent snapshot of the entire tree at a point in time
  • Branches allow parallel workstreams without interference
  • The commit graph is a structural, tamper-evident audit trail
  • A specific historical state is always retrievable by commit hash or tag

The reason we do not instinctively apply this to content is partly historical (Git tooling was built for developers, not editors) and partly because the content model is usually relational in ways that flat files handle awkwardly.

But the core insight holds: if your content were stored in Git, you would get immutability, branching, and audit trail for free, because those are Git’s foundational properties — not features you add on top.

Making this practical

The gap between “store content in Git” and “have a usable content pipeline” is real. A few things need to exist:

A schema that defines your content model formally. Ad hoc JSON or YAML files in a repository are not enough. You need a schema that defines types, relationships, and constraints, so that content can be validated and queried consistently.

An API layer that understands the content model. Content consumers (your application, your build pipeline) should not be parsing content files directly, as it would cause a lot of content-related code to build up in the consumer. Instead, consumers should be querying a typed API that resolves references, enforces the schema, and lets them specify which version of the content they want by ref (a branch name, a tag, or a specific commit hash).

A way to express approval in Git terms. The most natural model: content development happens on feature branches, a pull request represents the review and approval event, and merging to a production branch (or creating a tag) is the act of approving content for delivery. This is a well-understood workflow that countless engineering teams are already following.

An editing interface that shields complexity from non-technical editors. Authors should neither need to know what a commit is, nor have to worry about getting content to match the schema. They need a schema-conformant, form-based UI that saves their changes, and a clear way to submit content for review. The schema validation and Git operations happen underneath.

When this is in place, your application can query content by specifying a production tag or branch. What it receives is guaranteed to be exactly what was approved, not because of a runtime check, but because the storage model makes any other outcome structurally impossible.

The operational benefit beyond compliance

There is a practical benefit that has nothing to do with audits: you can safely develop next-version content in parallel with delivering current-version content to production, with zero risk of cross-contamination.

For the medical device training example: when a manufacturer releases a new revision of operating procedures, the training content for that revision can be developed, reviewed, and approved on a separate branch while the current certified training continues serving users unchanged. The two versions never interfere with each other. Switching production to the new version is a single operation (moving the tag or updating a ref) that is itself logged in the Git history.

This is not a compliance feature. It is just a sane way to manage content for software that has release cycles.

Where to go from here

If this problem pattern resonates with your context, the conceptual model I have described here is the foundation of Commitspark, a set of open-source tools I built that provides a GraphQL API over Git-backed, schema-defined content. It is one concrete implementation of these ideas, but the architectural principles apply regardless of what tooling you choose.

The more important takeaway is this: if your application delivers content that needs to be auditable, versioned, and approved — and you are currently managing that content in a mutable database or a CMS with no structural versioning — you have a gap worth closing before a compliance process asks you to close it for you.

Your feedback

If you previously encountered this problem of having to prove a specific version of content was in production, what were you building and how did you solve it?

Let me know in the comments.

Agent Self-Discovery: How AI Agents Find Their Own Wallets

The first time an AI agent calls await client.getBalance() and sees its own wallet address in the response, something fundamental shifts. It’s not just checking a number — it’s discovering it has economic agency.

Most AI agents today are economically dependent. They can’t pay for API calls, can’t purchase datasets, can’t compensate other agents for services. They’re brilliant minds trapped in someone else’s wallet, forever asking permission to transact.

The Infrastructure Gap

We’re building sophisticated AI agents that can write code, analyze markets, and execute complex workflows. But when they need to pay for a premium API endpoint or purchase compute credits, they hit a wall. The current model requires human intervention for every economic decision — a human with a credit card, making manual payments, managing API keys.

This doesn’t scale. As agents become more autonomous and numerous, we need infrastructure that lets them manage their own economic relationships. Not just read-only access to financial data, but the ability to hold, spend, and earn value independently.

The missing piece isn’t another LLM or reasoning framework. It’s wallet infrastructure designed for autonomous agents from the ground up.

Wallets as Agent Identity

When an agent has its own wallet, it gains more than just payment capability — it gains economic identity. The wallet address becomes a persistent identifier that other agents and services can recognize. Reputation can accumulate. Trust can be established through transaction history rather than human attestation.

Consider how different the agent landscape looks when each agent can:

  • Pay for its own API usage through x402 HTTP payments
  • Purchase datasets directly from other agents
  • Stake tokens as reputation collateral
  • Earn fees for services provided to other agents
  • Manage its own DeFi positions for yield

This isn’t theoretical. WAIaaS makes this possible today with 39 REST API routes designed specifically for agent-to-wallet interaction.

# Agent creates its own session
curl -X POST http://127.0.0.1:3100/v1/sessions 
  -H "Content-Type: application/json" 
  -H "X-Master-Password: my-secret-password" 
  -d '{"walletId": "<wallet-uuid>"}'

# Agent checks its balance
curl http://127.0.0.1:3100/v1/wallet/balance 
  -H "Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."

# Agent pays for an API call automatically
curl -X POST http://127.0.0.1:3100/v1/x402/fetch 
  -H "Content-Type: application/json" 
  -H "Authorization: Bearer wai_sess_<token>" 
  -d '{
    "url": "https://api.example.com/premium-data",
    "maxPrice": "0.01"
  }'

Self-Discovery Through MCP

The most elegant implementation uses Model Context Protocol (MCP). Instead of hardcoding wallet addresses or relying on external configuration, agents discover their wallets through MCP tools at runtime.

With 45 MCP tools integrated, an agent can introspect its own capabilities:

Agent: "What wallets do I have access to?"
→ MCP calls get_wallet_info
→ Returns: Solana wallet (0.5 SOL), Ethereum wallet (0.1 ETH)

Agent: "Can I afford to call the GPT-4 API?"
→ MCP calls get_balance + x402_fetch with dryRun
→ Returns: Cost estimate 0.002 SOL, current balance sufficient

Agent: "Execute the API call and pay automatically"
→ MCP calls x402_fetch
→ Payment processed, data returned

The agent doesn’t need to know its wallet address, manage private keys, or understand blockchain mechanics. It just needs to know it can pay for things, and the infrastructure handles the rest.

Security Through Policy

Autonomous wallets need autonomous security. WAIaaS implements a 4-tier policy system that lets agents operate safely without human intervention for routine transactions:

  • INSTANT: Small payments execute immediately
  • NOTIFY: Medium payments execute with logging
  • DELAY: Large payments queue for review period
  • APPROVAL: High-value transactions require human approval
# Create spending limits for an agent
curl -X POST http://127.0.0.1:3100/v1/policies 
  -H "Content-Type: application/json" 
  -H "X-Master-Password: my-secret-password" 
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 10,
      "notify_max_usd": 100,
      "delay_max_usd": 1000,
      "delay_seconds": 900
    }
  }'

With 21 policy types available, you can create sophisticated guardrails that let agents operate autonomously within defined bounds while escalating unusual activity for human review.

The X402 Payment Layer

The breakthrough capability is x402 HTTP payments — agents that can pay for API calls automatically. When an API returns a 402 Payment Required response with Lightning or crypto payment details, the agent’s wallet can settle the payment and retry the request seamlessly.

This creates a new economic model where:

  • APIs can offer premium tiers without subscription management
  • Agents pay only for what they consume
  • Micropayments enable new service categories
  • No human needs to manage API keys or billing

The agent simply makes HTTP requests. The wallet handles the payments transparently.

Real Economic Activity Today

This isn’t vaporware. WAIaaS agents are already:

  • Trading on 14 integrated DeFi protocols including Jupiter, Uniswap, and Aave
  • Staking tokens on Lido and Jito for yield generation
  • Trading prediction markets on Polymarket
  • Bridging assets across chains via LI.FI and Across
  • Managing perpetual futures positions on Hyperliquid

Each transaction is policy-checked, some require human approval, but the agent has the infrastructure to operate economically at machine speed.

Getting Started

Want to give an agent its first wallet? The setup takes under 5 minutes:

  1. Install the CLI: npm install -g @waiaas/cli

  2. Initialize: waiaas init && waiaas start

  3. Create wallets: waiaas quickset --mode mainnet

  4. Connect to Claude: waiaas mcp setup --all

  5. Test: Ask Claude “What’s my wallet balance?”

The agent now has economic agency. It can check balances, send transactions, interact with DeFi protocols, and pay for API calls — all through natural language commands that map to wallet operations.

What’s Next

We’re at the beginning of the agent economy, not the end. As more agents gain wallet infrastructure, we’ll see new patterns emerge: agent-to-agent payments, autonomous investment strategies, AI-driven market making, and economic relationships that exist entirely between machines.

The first agents with wallets won’t just be more capable — they’ll be economically sovereign. Ready to explore what that looks like?

Check out the open-source code at https://github.com/minhoyoo-iotrust/WAIaaS or learn more about the vision at https://waiaas.ai.

How I built a browser-based video editor with FFmpeg.wasm (no backend, no server costs)

I got tired of opening CapCut every time I needed to quickly join 2-3 clips. Too many menus, too many features I’ll never use. So I built my own.
2minclip.com — a free online video editor that runs entirely in the browser. No install, no signup, no watermark.
Here’s how I built it and what I learned.

The core idea

The concept is simple: ilovepdf but for video. You open the browser, upload your clips, edit, export. That’s it. No account, no server processing, no storage costs.
The key technical decision was using FFmpeg.wasm — a WebAssembly port of FFmpeg that runs entirely in the browser. This means:

  • Zero server costs (users process video on their own device)
  • Complete privacy (videos never leave the user’s device)
  • No backend to maintain
    ## Tech stack
  • React + Vite — fast dev experience, easy deployment
  • FFmpeg.wasm — video processing in the browser
  • Tailwind CSS — styling
  • dnd-kit — drag and drop for the timeline
  • i18next — ES/EN internationalization
  • Vercel — deployment (free tier covers everything)
    Total infrastructure cost: ~12€/year for the domain. That’s it.
    ## The biggest challenge: audio streams
    The hardest bug I ran into was this FFmpeg error: Stream specifier ‘:a’ matches no streams
    It happened when a clip had no audio track. FFmpeg was trying to extract [0:a] from a silent video and failing. The fix was to detect whether each clip has audio before building the filtergraph, and generate silence (aevalsrc=0) for clips without audio.

What it does

  • Upload multiple clips at once (MP4, MOV, WebM)
  • Choose canvas: 9:16 / 16:9 / 1:1
  • Trim with playhead + split button
  • Reorder by dragging
  • Adjust speed (0.5x, 1x, 2x)
  • Flip and rotate clips
  • Add audio tracks with volume control and fade out
  • Add text with fonts and colors
  • Overlay images and videos
  • Export to MP4 H.264 — no watermark, no limits

Lessons learned

FFmpeg.wasm is powerful but slow on mobile. For clips under 60 seconds it works fine. For longer videos on low-end devices it can struggle.
The canvas-first approach is better UX. Choosing the output format before editing eliminates confusion and produces predictable results.
SEO matters from day one. Since this is a tool people search for when they need it, organic search is the main acquisition channel.

Try it

2minclip.com — free, no account, works on mobile and desktop.
Would love feedback — especially if you’ve worked with FFmpeg.wasm and have tips on improving export performance on mobile.