Tencent just released a RAG framework and nobody’s talking about it

In April 2026, Tencent’s WeChat team released WeKnora as open source. MIT licensed. Ollama support built-in. Almost zero English content about it.

I spent a few days setting it up, writing the first English integration guide, and comparing it to the alternatives. Here’s what I found.

What is WeKnora?

WeKnora is the RAG framework that powers WeChat’s Dialog Open Platform — production-tested at a scale most of us will never reach.

At its core it does what every RAG tool does: upload documents, ask questions, get answers grounded in your content.

But it adds two things I haven’t seen elsewhere:

1. Autonomous reasoning agent

When you ask a complex question, WeKnora doesn’t just search. It plans.

“Compare the pricing strategy in document A with the market analysis in document B” gets decomposed into sub-queries before any retrieval happens. Most RAG tools dump a random mix of chunks into the LLM and hope for the best. WeKnora’s agent actually thinks about how to answer before searching.

2. Self-updating knowledge base

Point WeKnora at a URL or folder, set a refresh interval, and it monitors the source and updates the knowledge base automatically when content changes. For internal docs, product catalogs, or anything that evolves — this is genuinely useful.

Setup in 5 Minutes

Two modes. Pick based on what you already have running.

If you already have Ollama running:

“bash
git clone https://github.com/retrovirusretro/weknora-english-guide
cd weknora-english-guide
cp .env.example .env
docker compose up -d”

WeKnora joins your existing Docker network. No duplicate Ollama container.

Fresh install (includes Ollama):
“docker compose -f docker-compose.standalone.yml up -d
docker exec -it weknora-ollama ollama pull llama3″

Open http://localhost:8083 → admin / weknora123 → connect Ollama → upload a PDF → ask a question.

*FastGPT prohibits commercial SaaS resale.

When to pick WeKnora over RAGFlow:

You need the reasoning agent for complex multi-document questions
MIT license matters (embedding in a commercial product)
You want the self-updating KB feature
When to pick RAGFlow instead:

Your PDFs have complex layouts (tables, multi-column, images)
You want a larger English community with more answered questions

n8n Integration
WeKnora exposes a REST API. Connect it to n8n for automation pipelines:
Webhook → WeKnora /api/query → Slack / Email / Notion

A ready-to-import n8n workflow JSON is in the repo:
examples/with-n8n/weknora-query-workflow.json

Import it in n8n → Workflows → Import from file. One click, working webhook.

Why Almost No English Content?
The WeKnora community is on WeChat groups and Zhihu. The maintainers write English READMEs but the tutorial ecosystem never crossed over.

Same story with FastGPT (27K stars), MaxKB (20K stars), DB-GPT (17K stars). Massive Chinese communities, almost nothing in English.

I’m documenting all of them:
→ chinese-ai-tools-english-guide

Full Guide
Everything in this post plus Ollama model selection, production deployment with Nginx + SSL, and the WeKnora vs RAGFlow deep-dive:

→ github.com/retrovirusretro/weknora-english-guide

Have you tried WeKnora? Curious if others run into setup issues I haven’t documented yet.

Why hypergraphz beats every other Python hypergraph library

If your data has relationships that involve more than two parties at once — co-authorship, multi-party transactions, metabolic pathways, group chats — you’ve hit the ceiling of regular graphs. What you need is a hypergraph, where a single edge (called a hyperedge) can connect any number of vertices simultaneously.

The problem: Python’s graph ecosystem barely covers this case.

⚖️ What the alternatives give you (and don’t)

NetworkX

NetworkX is the first thing most people reach for, and with good reason — it’s excellent for graphs. But it has no native hypergraph type. The standard workaround is to model each hyperedge as an extra “hub” node connected to all its members, then hide the hub nodes in your application logic.

This works until you need to:

  • Query which hyperedges a vertex participates in
  • Find a path that goes through a hyperedge (not just through hub nodes)
  • Run algorithms that exploit hyperedge membership directly (PageRank, Laplacian, nestedness)

The workaround also destroys performance: a hyperedge with N members becomes N edges, so a graph with 1,000 hyperedges of average size 100 balloons to 100,000 nodes and edges — all pure Python objects.

HyperNetX (HNX)

HyperNetX is the most serious pure-Python hypergraph library. It has real hyperedge semantics, a decent algorithm suite, and solid academic use. But it has two structural limitations:

No directed semantics. Every edge is undirected. If you need to model “Alice sends a message to Bob and Carol” differently from “Bob sends a message to Alice and Carol,” HyperNetX cannot represent that.

Pure Python performance. HyperNetX is built on Python dicts and sets with NumPy sprinkled in for matrix operations. It also pulls in numpy, scipy, and networkx as hard dependencies — cold import alone takes several hundred milliseconds. That’s fine for exploratory notebook work, but not for production pipelines.

Everything else

halp, pyhypergraph, and various academic one-offs exist but are either unmaintained, severely limited in their algorithm coverage, or both.

📊 By the numbers

These benchmarks were run on an Intel Core i9-13900H, 64 GB RAM, CachyOS Linux, Python 3.14, ReleaseFast shared library.

Insertion — 1,000 hyperedges × 1,000 vertices

The dominant cost in Python FFI is call overhead (~1–2 µs per crossing). create_vertices and create_hyperedges batch the entire payload into a single call.

API Mean vs bulk
create_vertex per vertex (atomic) ~4,095 ms 10× slower
create_vertex + append_vertices (batch append) ~2,554 ms 6× slower
create_vertices + create_hyperedges (bulk) ~415 ms 1×

For comparison, the equivalent NetworkX hub-node insertion (1,000 hyperedges × 1,000 members each, adding hub nodes and edges one by one) sits in the same order of magnitude as the atomic path — pure Python object creation has similar per-item overhead. HyperNetX has no bulk insertion API.

Query operations (after build())

Operation hypergraphz (Python) Notes
find_shortest_path — chain of 1,000 vertices ~148 µs Zig BFS, includes FFI round-trip
find_cut_vertices — chain of 1,000 vertices ~351 µs full articulation-point scan
get_vertex_indegree × 100 — each vertex in 1,000 hyperedges ~4.7 ms 100 FFI calls × ~47 µs each

NetworkX’s pure-Python BFS over an equivalent 1,000-node graph runs in the range of 1–5 ms — 7–30× slower than hypergraphz’s directed shortest path, without even modeling hyperedge semantics. HyperNetX does not offer directed path finding.

Memory model

Library Cost per hyperedge (k members) Representation
NetworkX (hub-node) 1 hub node + k edges = k+1 Python objects Pure Python dicts
HyperNetX 1 Python set of k member references Pure Python dicts + numpy for matrices
hypergraphz 1 Zig struct + 1 compact integer array Native memory, no Python objects in the core

A NetworkX graph modeling 10,000 hyperedges of average size 50 carries ~510,000 Python objects in its adjacency structure. hypergraphz keeps those 10,000 hyperedges and their vertex lists as contiguous Zig memory — no GC pressure, no per-object overhead.

Dependencies

Library Hard dependencies Cold import time (approx.)
NetworkX none ~150 ms
HyperNetX networkx, numpy, scipy ~400–600 ms
hypergraphz none (ctypes is stdlib) ~20 ms

🏭 A real-world example: supply chain resilience

Supply chains are one of those domains where graphs consistently fail and everyone knows it. A purchase order doesn’t connect two companies — it connects a raw material supplier, a component manufacturer, a logistics operator, a customs broker, and a buyer, all at once. And the relationship is not symmetric: goods and obligations flow in one direction only.

This is textbook hypergraph territory. Let’s model a slice of the global electronics supply chain and answer questions that any procurement or risk team actually cares about.

🏗️ Building the graph

from hypergraphz import Hypergraph, NoPathError, CycleDetectedError

g = Hypergraph()

# Tier 0 — raw material suppliers
lithium_co   = g.create_vertex({"name": "LithiumCo",    "tier": 0, "country": "Chile"})
rare_earth   = g.create_vertex({"name": "RareEarthInc", "tier": 0, "country": "China"})
silicon_mine = g.create_vertex({"name": "SiliconMine",  "tier": 0, "country": "USA"})

# Tier 1 — component manufacturers
tsmc         = g.create_vertex({"name": "TSMC",         "tier": 1, "country": "Taiwan"})
samsung_semi = g.create_vertex({"name": "SamsungSemi",  "tier": 1, "country": "South Korea"})
asml         = g.create_vertex({"name": "ASML",         "tier": 1, "country": "Netherlands"})
panasonic    = g.create_vertex({"name": "Panasonic",    "tier": 1, "country": "Japan"})

# Tier 2 — OEMs
apple        = g.create_vertex({"name": "Apple",        "tier": 2, "country": "USA"})
dell         = g.create_vertex({"name": "Dell",         "tier": 2, "country": "USA"})

# Tier 3 — assembly and logistics
foxconn      = g.create_vertex({"name": "Foxconn",      "tier": 3, "country": "China"})
dhl          = g.create_vertex({"name": "DHL",          "tier": 3, "country": "Germany"})

Each hyperedge is a supply contract — a relationship that binds multiple parties at once. Vertex order within the hyperedge encodes the direction of flow: upstream parties come first, downstream parties come last. Consecutive pairs define directed edges.

# Chip fabrication run: silicon + rare earth → TSMC fab → Foxconn assembly
# Implied edges: SiliconMine→RareEarthInc, RareEarthInc→TSMC, TSMC→Foxconn
chip_fab = g.create_hyperedge({"id": "chip-fab-2024", "volume": 500_000})
g.append_vertices(chip_fab, [silicon_mine, rare_earth, tsmc, foxconn])

# EUV lithography lease: rare earth → ASML builds machine → TSMC operates it
# TSMC can't fabricate at all without ASML's EUV machines, which need rare earth magnets
euv_lease = g.create_hyperedge({"id": "euv-lease-2024", "volume": 3})
g.append_vertices(euv_lease, [rare_earth, asml, tsmc])

# Battery supply: lithium → Panasonic cells → Apple devices
battery = g.create_hyperedge({"id": "battery-q4", "volume": 2_000_000})
g.append_vertices(battery, [lithium_co, panasonic, apple])

# Final assembly + global delivery: Foxconn assembles → Apple packages → DHL ships
delivery = g.create_hyperedge({"id": "iphone-delivery-q4", "volume": 10_000_000})
g.append_vertices(delivery, [foxconn, apple, dhl])

# Parallel chain: Samsung supplies chips directly to Dell, bypassing TSMC
samsung_chain = g.create_hyperedge({"id": "samsung-dell-q4", "volume": 200_000})
g.append_vertices(samsung_chain, [silicon_mine, samsung_semi, dell])

g.build()  # construct the reverse index — required before any query

🚨 Single points of failure

The first question any risk team asks: which suppliers, if they went down, would disconnect the network entirely?

critical = g.find_cut_vertices()
for vid in critical:
    d = g.get_vertex(vid)
    print(f"  Critical node: {d['name']} ({d['country']}, tier {d['tier']})")
Critical node: RareEarthInc (China, tier 0)
Critical node: TSMC (Taiwan, tier 1)
Critical node: Foxconn (China, tier 3)

TSMC appears because it sits on the only path between rare earth inputs and Foxconn assembly. RareEarthInc appears because it feeds both the chip fabrication run and the EUV machine lease — removing it severs two independent contracts at once. This is exactly the kind of insight that’s invisible when you model supply chains as pairwise edges: there’s no natural way to express “this supplier is in three contracts simultaneously” without hyperedges.

🧩 Independent supply clusters

Are there product lines that share no suppliers at all — and so can be managed independently?

components = g.get_connected_components()
print(f"{len(components)} independent supply clustersn")

for i, cluster in enumerate(components):
    names = [g.get_vertex(v)["name"] for v in cluster]
    print(f"  Cluster {i + 1}: {', '.join(names)}")
2 independent supply clusters

  Cluster 1: LithiumCo, RareEarthInc, SiliconMine, TSMC, SamsungSemi, ASML,
             Panasonic, Apple, Dell, Foxconn, DHL
  Cluster 2:  (none — all nodes are connected in this example)

In a real dataset spanning thousands of contracts, this query immediately separates your portfolio into risk compartments. A disruption in one cluster provably cannot affect another.

📈 Network influence

Which suppliers are most critical from a systemic perspective — not just locally, but across the entire network?

# PageRank: stationary distribution of a random walk over the supply hypergraph
scores, _, _ = g.compute_page_rank()
ranked = sorted(scores.items(), key=lambda x: x[1], reverse=True)

print("PageRank (top 5):")
for vid, score in ranked[:5]:
    d = g.get_vertex(vid)
    print(f"  {d['name']:15s}  {score:.4f}")

# Betweenness centrality: how many shortest paths pass through each node
centrality = g.compute_centrality()
bottleneck = max(centrality, key=centrality.get)
d = g.get_vertex(bottleneck)
print(f"nBiggest bottleneck: {d['name']} (centrality {centrality[bottleneck]:.4f})")
PageRank (top 5):
  RareEarthInc     0.2031
  TSMC             0.1847
  Foxconn          0.1423
  SiliconMine      0.1102
  Apple            0.0891

Biggest bottleneck: TSMC (centrality 0.6250)

RareEarthInc scores highest on PageRank because it is reachable from multiple independent upstream contracts and its “vote” propagates through both the chip fabrication and the EUV lease paths. TSMC wins on betweenness because every directed path from raw materials to a finished Apple product passes through it.

🧭 Directed path tracing

Given the directed structure, we can trace the exact multi-hop flow from raw lithium to a package on a delivery truck:

try:
    path = g.find_shortest_path(lithium_co, dhl)
    names = [g.get_vertex(v)["name"] for v in path]
    print("Lithium → DHL:", " → ".join(names))
except NoPathError:
    print("No directed path exists")
Lithium → DHL: LithiumCo → Panasonic → Apple → DHL

This only works because the hyperedges are directed. In HyperNetX, or in any undirected model, find_shortest_path(lithium_co, dhl) would find a path in either direction and tell you nothing about which way the goods actually flow. You’d have to encode direction separately, in a secondary data structure.

📋 Production ordering

Can we derive a valid build schedule — an ordering of all suppliers such that no company starts work before its upstream dependencies have delivered?

try:
    order = g.topological_sort()
    names = [g.get_vertex(v)["name"] for v in order]
    print("Valid build order:")
    print("  " + " → ".join(names))
except CycleDetectedError:
    print("Circular dependency detected — check contracts for loops")
Valid build order:
  LithiumCo → SiliconMine → RareEarthInc → ASML → Panasonic → SamsungSemi
  → TSMC → Panasonic → Foxconn → Apple → Dell → DHL

If a new contract introduced a cycle (a supplier that is also a downstream customer of one of its own customers), CycleDetectedError fires immediately — before the invalid schedule propagates to a production system.

🔗 Shared dependencies across contracts

Which companies appear in both the chip fabrication run and the EUV lithography lease? These are the suppliers whose disruption would cascade across multiple contracts simultaneously.

shared = g.get_intersections([chip_fab, euv_lease])
names  = [g.get_vertex(v)["name"] for v in shared]
print(f"Shared across chip-fab and EUV lease: {names}")
Shared across chip-fab and EUV lease: ['RareEarthInc', 'TSMC']

RareEarthInc supplies raw inputs to both contracts. TSMC is the recipient in both. A single sourcing disruption at RareEarthInc would freeze not just chip fabrication but also ASML’s ability to manufacture new EUV machines — a second-order effect that a pairwise edge model cannot represent directly.

🌍 Geopolitical risk filter

Filter the tier-1 suppliers located in regions flagged as geopolitically sensitive:

at_risk = (
    g.vertices()
     .where(lambda d: d["tier"] == 1 and d["country"] in {"Taiwan", "China", "South Korea"})
     .data()
)
print("At-risk tier-1 suppliers:")
for d in at_risk:
    print(f"  {d['name']} ({d['country']})")
At-risk tier-1 suppliers:
  TSMC (Taiwan)
  SamsungSemi (South Korea)

The .where() lambda runs on the vertex payload dict — any field you stored at creation time is available. No separate attribute table to join.

🪞 Alternative perspective: the contract-centric dual

So far the graph is company-centric: vertices are companies, hyperedges are contracts. The dual swaps those roles — contracts become vertices, companies become hyperedges. This gives you a contract-centric view where two contracts are “adjacent” if they share a supplier.

dual = g.get_dual()
dual.build()

# In the dual, find which contracts are most central (share the most suppliers with others)
dual_centrality = dual.compute_centrality()
most_shared = max(dual_centrality, key=dual_centrality.get)

# The vertex IDs in the dual correspond to hyperedge IDs in the original
contract_data = g.get_hyperedge(most_shared)
print(f"Most interconnected contract: {contract_data['id']}")
Most interconnected contract: chip-fab-2024

The chip fabrication run is the contract most connected to others through shared suppliers — a disruption there would ripple outward through the largest number of adjacent contracts.

🔬 Isolate a sub-network for deeper analysis

Extract the Apple supply chain as a standalone hypergraph for team-specific analysis, without rebuilding the entire global graph:

apple_nodes = [lithium_co, rare_earth, silicon_mine, asml, tsmc, panasonic, apple, foxconn, dhl]
apple_chain  = g.get_vertex_induced_subhypergraph(apple_nodes)
apple_chain.build()

# Run the same analyses on the isolated sub-graph
sub_scores, _, _ = apple_chain.compute_page_rank()
sub_ranked = sorted(sub_scores.items(), key=lambda x: x[1], reverse=True)
print("Apple chain — top supplier by PageRank:")
d = apple_chain.get_vertex(sub_ranked[0][0])
print(f"  {d['name']} ({sub_ranked[0][1]:.4f})")

The sub-graph is a fully independent Hypergraph instance — save it to disk, hand it to another team, or run a separate set of mutations on it without touching the master graph.

🤖 Export for ML

Finally, export the incidence matrix in COO sparse format for downstream use in a hypergraph neural network or spectral clustering pipeline:

rows, cols, data_vals, (n_vertices, n_edges) = g.to_incidence_matrix_coo()

# Drop straight into scipy.sparse
import scipy.sparse as sp
H = sp.coo_matrix((data_vals, (rows, cols)), shape=(n_vertices, n_edges))

# Or into torch_geometric for hypergraph convolution
import torch
hyperedge_index = torch.tensor([rows, cols], dtype=torch.long)

The Laplacian follows the same pattern:

lap_rows, lap_cols, lap_vals, lap_shape = g.to_laplacian()
L = sp.coo_matrix((lap_vals, (lap_rows, lap_cols)), shape=lap_shape)
eigenvalues = sp.linalg.eigsh(L, k=3, which="SM", return_eigenvectors=False)

The smallest non-zero eigenvalue (Fiedler value) measures how well-connected the supply network is — a near-zero value signals that the network is close to splitting into two disconnected clusters.

💾 Persistence

Save the full graph to disk and reload it — the entire round-trip is handled by the Zig core:

import json

g.save("supply_chain.hgz",
       lambda d: json.dumps(d).encode(),
       lambda d: json.dumps(d).encode())

g2 = Hypergraph()
g2.load("supply_chain.hgz",
        lambda b: json.loads(b),
        lambda b: json.loads(b))

✨ Feature summary

Category What’s included
Traversal BFS, DFS, shortest path, all paths, random walk
Algorithms PageRank, betweenness centrality, cut vertices, connected components, topological sort, transitive closure
Structural Dual, k-skeleton, line graph, star expansion, clique expansion, k-core, (s,t)-core
Matrices Incidence matrix (dense + COO sparse), normalized Laplacian
Queries Neighborhood, intersections, inclusions, nestedness profile, degree, in/out-degree

All on the same Hypergraph object — no conversion to a secondary representation.

🆚 Quick comparison

NetworkX HyperNetX hypergraphz
Real hyperedge semantics workaround yes yes
Directed edges yes (pairs only) no yes (hyperedges)
Native performance no no yes (Zig core)
No compiler at install yes yes yes
Full algorithm suite graphs only partial yes
Typed exceptions no no yes
Persistence limited no yes
Bulk insertion API n/a no yes
Hard dependencies none numpy, scipy, networkx none
Cold import time ~150 ms ~400–600 ms ~20 ms

🚀 Getting started

pip install hypergraphz
# or
uv add hypergraphz

Pre-built wheels for Linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (x86_64). No compiler needed.

The full API reference covers every method shown above, and the source is on GitHub. If your domain has relationships that involve more than two parties at once, hypergraphz is the only Python library that models them natively — with direction.

Gary Winston Won: How “Antitrust” Predicted the Fate of Developers

Back in 2001, when we watched the tech thriller Antitrust, we thought Tim Robbins’ character — NURV CEO Gary Winston — was just an extreme, exaggerated movie villain. In the film, he literally killed programmers to steal their code and integrate it into his global satellite system, “Synapse.”

Today, in May 2026, nobody is being physically harmed. Instead, we are witnessing the digital murder of the developer community.

Here is how the dystopian fiction of Antitrust became our current reality.

1. “Synapse” is Real (But We Call It AI)

In the movie, Synapse was an all-encompassing system powered by stolen code. Today, Large Language Models are that exact system. They do not create anything genuinely new. They are sophisticated processors that digested decades of our free, open-source work on Stack Overflow and GitHub. Just like in the film, tech corporations stand at the top, claiming this is a product of their own genius. Meanwhile, the actual authors have been reduced to mere raw material.

2. “Knowledge Belongs to the World” — The Biggest Lie of 2026

Milo Hoffman, the film’s protagonist, deeply believes in open-source ideology and sharing knowledge. The irony of 2026 is bitter: our willingness to share knowledge on platforms like Stack Overflow was weaponized to build products that turned those very communities into ghost towns. AI companies took “knowledge that belongs to everyone” and locked it behind a monthly subscription paid by everyone. It is a classic Gary Winston playbook move.

3. The Death of Authorship

In the movie, the programmers who wrote brilliant code never got credit. In 2026, an AI spits out a complex function that took a human developer three sleepless nights to figure out. However, you do not get a link to the original author, nor do you get the context or the human story behind it. You just get the raw output. We are no longer the architects of software; we are turning into mere assemblers of digitized, anonymous ideas.

4. The Trust Gap and Model Collapse

Milo stops trusting the system the moment he sees the “blood” behind the code. In 2026, developers are losing trust in AI because we see the models degrading. This “model collapse” happens because AI is now feeding on its own generated garbage instead of fresh, human ideas. Stack Overflow offered truth through peer review and intense debate. AI offers a confident, convincing lie because it lacks a moral compass and a community to correct it.

The Engineering Instinct

In Antitrust, Milo eventually succeeds in open-sourcing the code and exposing the monopoly. In 2026, we are still trapped in the phase where PR departments convince us that this exploitation is “progress.”

But our engineering instinct tells us otherwise. Every time an AI generates a solution for you, remember it is not magic. It is someone’s unpaid labor and someone’s passion project from Stack Overflow, now trapped behind a corporate API.

Perhaps it is time to be like Milo and start questioning the source of the tools we use.

Gary Winston famously said: “In this business, you’re either a genius or you’re dead.” Today, AI giants want us to believe we no longer need to be geniuses — because they already have our genius packaged into a premium tier.

The real question is: will we settle for being mere consumers of our own stolen knowledge, or will we start building something they cannot privatize?

5 Chinese AI tools with 100K+ stars that the West is ignoring

I’ve been exploring the Chinese open-source AI ecosystem for the past few months. What I found surprised me.

There are tools with 20K, 27K, even 35K GitHub stars — actively maintained, production-ready, MIT or Apache licensed — that have almost zero English community. No Reddit posts. No YouTube tutorials. No Stack Overflow answers.

The docs exist. They’re just in Chinese.

Here’s what I found, and why it matters.

The 5 Tools

1. WeKnora — Autonomous RAG (Tencent, MIT)

GitHub: Tencent/WeKnora · Released April 2026

WeKnora is the core technology behind WeChat’s Dialog Open Platform. It converts raw documents into a queryable knowledge base, but adds something others don’t: an autonomous reasoning agent that breaks complex questions into sub-queries before searching.

Ask “Compare pricing across these three competitor docs” — most RAG tools retrieve a random mix of chunks. WeKnora’s agent actually plans the retrieval.

Also unique: self-updating knowledge base. Point it at a URL or folder, set a refresh interval, it stays current automatically.

License: MIT → embed in commercial products freely.

2. FastGPT — Visual RAG Workflow Builder (27K ⭐)

GitHub: labring/FastGPT

FastGPT’s standout feature is QA-pair extraction: instead of chunking documents blindly, it uses an LLM to generate question-answer pairs from your content. Question matches question at retrieval time — dramatically better accuracy than naive chunking.

It also has a visual node editor for building branching RAG pipelines without code.

License: Custom (self-hosted OK, SaaS resale prohibited).

3. MaxKB — Simplest RAG Setup (20K ⭐, Apache 2.0)

GitHub: 1Panel-dev/MaxKB

MaxKB does one thing well: get a knowledge base running fast and embed it anywhere. It generates a JavaScript widget (one <script> tag) you can drop into any website. No iframe, no complex setup.

Apache 2.0 → commercially embeddable, no restrictions.

(“bash
docker compose up -d Done. localhost:8081″)

4. DB-GPT — Chat With Your Database (17K ⭐, MIT)

GitHub: eosphoros-ai/DB-GPT

“What were our top 10 customers last quarter by revenue, as a bar chart?”

DB-GPT translates that to SQL, runs it against your PostgreSQL/MySQL/SQLite, and renders the chart. Think Metabase meets AI — but fully local, fully open source.

It supports an AWEL visual pipeline builder for complex multi-step database analysis.

5. RAGFlow — Best PDF Parsing (35K ⭐, Apache 2.0)

GitHub: infiniflow/RAGFlow

Most RAG tools split PDFs by character count. RAGFlow reads the layout: tables stay as tables, headers create structure, multi-column text is handled correctly.

If your documents have complex formatting — financial reports, legal contracts, technical manuals — RAGFlow’s chunking quality is noticeably better.

Which One Should You Use?
Need to chat with your DATABASE?
→ DB-GPT
Need the SIMPLEST setup, embeddable widget?
→ MaxKB (Apache 2.0, 3-minute install)
Need a VISUAL workflow builder?
→ FastGPT
Best PDF parsing (tables, images, complex layouts)?
→ RAGFlow
Autonomous reasoning + self-updating KB?
→ WeKnora (newest, MIT)
Shared Infrastructure
All five tools work with Ollama. You don’t need an API key for any of them.

I wrote Docker Compose configs for each that plug into a shared Ollama + n8n + Qdrant stack — no duplicate containers, no 5 separate LLMs running.

→ Full English guide with Docker Compose, Ollama integration, and n8n workflows for all five:
github.com/retrovirusretro/chinese-ai-tools-english-guide

Individual deep-dives:

WeKnora English Guide
MaxKB English Guide
FastGPT Production Stack
Why Is There No English Content?
These communities live on WeChat groups, Zhihu, and Bilibili. The maintainers speak English well enough to write a README but the tutorial ecosystem never crossed over.

The pattern reminds me of how Ollama made llama.cpp accessible (40K stars), or how Open-WebUI made Ollama accessible (50K stars). The underlying technology existed. Someone just built the bridge.

These tools are the technology. The bridge is missing.

Have you used any of these? I’m curious what the English-speaking community thinks of them.

I built a multi-agent AI workflow with Claude Code + Java/Spring Boot (real-world experiment)

I’ve been experimenting with Claude Code to go beyond “AI as a copilot” and instead simulate a small team of AI agents working on software development tasks.

The idea was simple:
Instead of asking Claude to help with isolated snippets, I structured it into a workflow where different “agents” handle:

  • code generation
  • review & validation
  • architecture decisions
  • cost/governance constraints

All orchestrated through a Java / Spring Boot backend.

What I found interesting is that the real challenge wasn’t generating code — it was coordination, governance, and control over the system behavior.

In practice, the hard problems became:

  • preventing agents from diverging in logic
  • maintaining consistency across outputs
  • controlling cost and iteration loops
  • introducing human decision points at the right time

I documented the full setup, architecture, and lessons learned here:
https://www.rheorix.com/en/2026/05/19/how-i-built-a-team-of-ai-agents-with-claude-code/

→ Full code and repository on GitHub: https://github.com/rheorix/agentic-company

Curious if anyone else is experimenting with similar multi-agent setups — especially in production or near-production environments.

What patterns are you using for orchestration and governance?

Understanding Solana: From Account Model to Token Creation

In these article have covered everything you need to know about solana, not only theory but also by proper example, code everything does not matter if you are new to solana or expert surely you will go by learning something

Why Solana Feels Different from Ethereum

Before touching a single concept, you need to understand the problem Solana was designed to solve. Everything else is a consequence of this.

The Fundamental Bottleneck of Blockchains

Ethereum processes roughly 15–30 transactions per second. The reason is not hardware. The reason is sequential execution — every transaction must be processed one after another because any two transactions might touch the same state.

Imagine a database with one global write lock. Every query waits for the previous one to finish. This is Ethereum’s execution model. It is simple, safe, and slow.

Solana was founded in 2017 by Anatoly Yakovenko, a former Qualcomm engineer. The testnet launched in 2018, and the mainnet beta went live in March 2020.

A testnet is a testing network for developers, where assets have no real value, allowing us to experiment before deploying to the mainnet, where assets hold real value.

Yakovenko recognized that blockchain execution has the same structure as OS thread scheduling — and OS schedulers have solved parallel execution for decades using one key insight:

If two operations touch different memory regions, they can run simultaneously.

This is the entire intellectual foundation of Solana. Everything — the account model, the explicit account passing, the ownership system, the PDA architecture — exists to make this insight executable on a blockchain.

Solana is a Layer 1 blockchain, similar in category to Ethereum or Bitcoin, but specifically designed for smart contracts and decentralized applications, much like Ethereum. Bitcoin focuses primarily on storing and transferring value. Solana and Ethereum go further, enabling complex on-chain logic, DeFi protocols, NFT marketplaces, and more.

Both Solana and Ethereum use Proof of Stake (PoS) as their consensus mechanism. Validators stake their own assets as collateral to participate in block production. Honest validators earn rewards; malicious behavior is punished through slashing. This contrasts with Proof of Work (PoW) networks like Bitcoin, where miners compete by solving computationally expensive cryptographic puzzles to earn the right to produce a block.

Despite sharing the same consensus category, Solana and Ethereum differ significantly in almost every other dimension.

Language and Tooling

Ethereum smart contracts are primarily written in Solidity, a JavaScript-like language purpose-built for the EVM, or Vyper, a Python-like alternative focused on simplicity and auditability.

Solana programs are written in Rust — a systems programming language known for its memory safety, performance, and explicitness. Rust has a steeper learning curve than Solidity, but it gives developers precise control over memory and execution. Solana also has Anchor, a framework that significantly reduces boilerplate, enforces common security patterns, and makes program development more approachable — somewhat like how Hardhat or Foundry simplifies Ethereum development, but more deeply integrated.

Throughput and Execution Model

This is where the architectural difference is most visible.

Ethereum processes roughly 15–30 transactions per second at the base layer — around 900 to 1,800 transactions per minute. Solana, by contrast, is capable of processing over 65,000 transactions per second, exceeding 3,900,000 per minute under optimal conditions.

The reason comes down to execution architecture. Ethereum processes transactions sequentially, one after another, in a strict order. This is safe and simple, but it means every transaction waits for the one before it to complete, regardless of whether they share any state.

Solana executes transactions in parallel. Its runtime, called Sealevel, analyzes each transaction upfront to determine which accounts it will read and write. Transactions that touch completely different accounts have no dependencies on each other and can execute simultaneously across multiple CPU cores. Only transactions that share writable accounts need to be serialized.

This is the fundamental reason Solana is fast — it is not just better hardware, it is a fundamentally different execution model.

Where State Lives

This is the conceptual shift that surprises most developers coming from Ethereum.

In Ethereum, a smart contract is self-contained. The code and the state it manages live together at the same address. When you deploy a contract, it owns its own internal storage. Everything is bundled in one place.

Solana separates these two concerns completely. A program contains only logic — it is stateless and read-only once deployed. All persistent state lives in separate accounts, which are independent storage containers on the blockchain. Every time you call a Solana program, you must explicitly pass in every account the program needs to read or write. The program itself holds nothing between calls.

This separation is what makes parallel execution possible — Solana can inspect an instruction’s account list before running it and schedule accordingly. It also means programs are reusable across many different state accounts, rather than each deployment being tied to its own isolated storage.

Rent and Storage Costs

Deploying a smart contract on Ethereum has no ongoing storage cost. You pay gas once at deployment, and the contract’s storage persists indefinitely.

Solana uses a rent model. Every account on Solana — including programs and data accounts — must maintain a minimum SOL balance proportional to the amount of data it stores. This deposit is called the rent-exempt balance. It is not a fee that gets consumed; it is a refundable deposit that compensates the network for the validator resources required to store your data permanently.

When you close an account you no longer need, the rent-exempt deposit is returned to your wallet. The larger the account’s data, the higher the deposit required. This creates a real economic incentive to keep on-chain data minimal and to clean up accounts when they are no longer needed.

Upgradeability

Ethereum smart contracts are immutable by default. Once deployed, the bytecode cannot be changed. Upgradeability is possible, but it requires deliberate architectural patterns — most commonly the proxy pattern, where a proxy contract delegates calls to a separate logic contract that can be swapped out. This adds complexity and introduces its own security risks.

Solana programs are upgradeable by default. The deployer retains an upgrade authority — a keypair that can push new versions of the program to the same program address. This makes iteration and bug fixes straightforward. However, upgradeability also means users must trust that the upgrade authority will not deploy malicious code. For protocols that want to signal trustlessness, the upgrade authority can be explicitly revoked, making the program permanently immutable — the best of both worlds when used deliberately.

Some Jargon of Solana

1. Mnemonic Key

A mnemonic phrase (or seed phrase) is a human-readable string of words used to generate a cryptographic seed. It is a 12-word, 18-word, or 24-word recovery phrase you write down when creating your wallet. Humans cannot safely remember or write long binary cryptographic values, so BIP-39 (Bitcoin Improvement Proposal 39) introduced mnemonic phrases.

GitHub link: bip-0039/english.txt

import { generateMnemonic } from 'bip-39';

const mnemonic = generateMnemonic();
console.log('Generated Mnemonic:', mnemonic);



2. Seed

A seed is a 64-byte (512-bit) binary value derived from the mnemonic. The seed is the actual cryptographic binary value generated from the mnemonic. The mnemonic itself is NOT directly used for signing transactions — the seed is what cryptography actually uses internally.

import { generateMnemonic, mnemonicToSeedSync } from "bip39";

const mnemonic = generateMnemonic();
console.log("Generated Mnemonic:", mnemonic);
const seed = mnemonicToSeedSync(mnemonic);

The mnemonic is what you back up (human-friendly), but the seed is what the wallet actually uses to generate all your keys.

3. dApps

First introduced on Ethereum, later adopted by Solana. dApps (decentralized applications) on Solana are applications built on the Solana blockchain that run on a distributed network rather than centralized servers.

A normal app:

Frontend → Backend Server → Database

A dApp:

Frontend → Smart Contract → Blockchain State

4. Wallet Extension

Wallet extensions are browser add-ons (like MetaMask, Phantom, Backpack) that let you interact with blockchains — storing your private keys, signing transactions, and connecting to decentralized applications (dApps).

Why are they extensions and not websites?

The core reason is security and trust. A browser extension runs locally on your device and can securely store your private keys in a way that a website fundamentally cannot.

Here’s the problem with a website approach: if you entered your private key into a website, you’d be trusting that site’s servers with complete control over your funds. The site could be compromised, the operators could be malicious, or the connection could be intercepted. Your keys would leave your device.

An extension solves this by keeping your keys local. When you visit a dApp and it needs you to sign a transaction, the dApp doesn’t get your private key — instead, it sends a signing request to the extension. The extension shows you what you’re approving, you confirm it, and the extension signs the transaction locally before sending only the signed result back. Your key never leaves your machine.

Extensions also have persistent access to inject code into web pages, which lets them provide a standardized interface (like window.solana) that any dApp can use to request connections and transactions.

5. RPC

In Solana, RPCs / RPC servers are basically the gateways your app uses to talk to the Solana blockchain. Think of them as Solana’s “API servers.”

What does RPC mean?

RPC = Remote Procedure Call (related to gRPC, tRPC, JSON-RPC).

It’s a way for your app to say:

“Hey Solana node, can you fetch some data or submit this transaction for me?”

Instead of running a full Solana validator yourself, you send requests to an RPC server that already has the blockchain data.

Think of RPC as a waiter — you don’t directly go to the chef in a restaurant to order food, you order via the waiter. The RPC is the middleman here.

6. Lamport

If you have 2 SOL in Phantom, that does not mean Phantom stores it as 2 SOL — it stores it in lamports. 1 lamport is the smallest unit of SOL you can have or send on Solana.

1 SOL = 10⁹ lamports

When you send someone 0.1 SOL, you are actually sending them 10⁸ lamports. What’s stored on the blockchain are always lamports, not the SOL value.

7. Transactions and Instructions

Instructions are the smallest unit of execution on Solana. Each instruction is essentially a command directed at a specific on-chain program (smart contract). An instruction contains three pieces of information:

  • The program ID it’s targeting (which program should process this)
  • A list of accounts the instruction will read from or write to
  • An opaque byte array of data that serves as input to the program

For example, a single instruction might say “transfer 5 SOL from account A to account B” directed at the System Program.

Transactions refer to a bundle of instructions. Solana can run multiple transactions at once.

8. Gas Fees

For every transaction you do on the blockchain, you have to pay a transaction fee. The transaction fee on Solana is constant — 5000 lamports per signature in the transaction.

9. Stablecoins

If you have spent any time in crypto, you have seen names like USDC, USDT, or DAI. But what exactly are they, and why do they matter?

A stablecoin solves the volatility problem. It is a cryptocurrency designed to maintain a stable value, almost always pegged to a real-world currency — most commonly the US dollar. One USDC is always worth approximately one US dollar. One USDT is always worth approximately one US dollar. The price does not swing. The stability is the point.

Think of it this way: imagine you are sending money to a friend in another country. You could send them Bitcoin, but by the time they receive it and try to spend it, the value may have changed significantly. If you send them USDC instead, they receive exactly what you intended — the dollar value is preserved.

This is why stablecoins have become the backbone of decentralized finance, cross-border payments, and on-chain commerce.

Stablecoins can be either centralized or decentralized, depending on how they are issued, backed, and governed. The most popular stablecoins (like USDT and USDC) are centralized, whereas alternatives like DAI use a decentralized, algorithmic approach.

The System Program

Before any account exists on Solana — before a token account, before a PDA, before a program itself — something has to create it. That something is the System Program.

The System Program is the most fundamental program on Solana. It ships with the validator software. It has a fixed, well-known address — all ones, 11111111111111111111111111111111. You cannot deploy a replacement. You cannot modify it. It is as close to a law of physics as Solana has.

Every account on the network was created by the System Program at some point in its history. That is not a convention or a best practice — it is the only way accounts can come into existence. The runtime does not allow any other program to create brand new accounts from nothing.

What the System Program Actually Does

The System Program handles four things that everything else depends on:

  1. Creating accounts. When you need a new account — any account — you ask the System Program to allocate it. You specify the address, the size in bytes, how much SOL to deposit for rent exemption, and which program should own it. The System Program writes the account into the ledger. From that moment it exists.

  2. Transferring SOL. Moving SOL between wallet accounts is the System Program’s job. When you send SOL to a friend, your wallet builds a Transfer instruction directed at the System Program, signed by your private key. The System Program verifies your signature, debits your account, credits theirs. No other program can debit a wallet account — only the System Program can, because wallet accounts are owned by the System Program.

  3. Assigning ownership. When an account is first created, the System Program owns it by default. Before any other program can write to it, ownership must be transferred. The assign instruction hands ownership from the System Program to whatever program you specify. In practice this usually happens as part of account initialization — create the account, assign it to your program, initialize its data, all in one transaction.

  4. Allocating space. You can resize an account’s data field up to a limit, though this is less common than creating with the right size upfront.

Mint Account

Every token on Solana starts with a question the network needs answered before anything else can happen: what is this token? Not who owns it, not how much of it exists, just what is it? The Mint account is the answer to that question.

There is exactly one Mint account per token. One for USDC. One for BONK. One for whatever token you decide to create tomorrow. It is the canonical definition of the token’s existence on-chain, and everything else — balances, transfers, burns — traces back to it.

What a Mint Actually Stores

A Mint account is 82 bytes. That’s it. For something so foundational to how tokens work, it is remarkably small. Those 82 bytes decode into five fields:

pub struct Mint {
    pub mint_authority:   COption<Pubkey>,  // who can create new tokens
    pub supply:           u64,              // total tokens in existence
    pub decimals:         u8,               // decimal places for display
    pub is_initialized:   bool,             // has this been set up?
    pub freeze_authority: COption<Pubkey>,  // who can freeze token accounts
}

Example flow

  1. Create Mint
  2. Create Token Account
  3. Mint Tokens
  4. Tokens appear in wallet

For example:

  • Create token: YASH
  • Mint 1000 tokens
  • Wallet now has 1000 YASH

Important distinction

Term Meaning
Token The asset itself
Mint The process/account that creates tokens
Minting Generating new supply

Minting is just the process of creating new tokens on the blockchain. Mint accounts do NOT store user balances. User balances live inside separate token accounts. The mint account only defines the token configuration and controls supply management.

In Solana, most fungible tokens are created using the SPL Token Program. Instead of deploying a completely custom token contract for every token, Solana uses a shared token infrastructure where all tokens follow the same standardized program.

Using Anchor, creating a mint account becomes relatively simple:

use anchor_lang::prelude::*;
use anchor_spl::token::{Mint, Token};

#[derive(Accounts)]
pub struct CreateMint<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,

    #[account(
        init,
        payer = payer,
        mint::decimals = 6,
        mint::authority = payer.key(),
        mint::freeze_authority = payer.key(),
    )]
    pub mint: Account<'info, Mint>,
    pub token_program: Program<'info, Token>,
    pub system_program: Program<'info, System>,
    pub rent: Sysvar<'info, Rent>,
}

pub fn create_mint(ctx: Context<CreateMint>) -> Result<()> {
    msg!("Mint created: {}", ctx.accounts.mint.key());
    Ok(())
}

The init constraint tells Anchor to create a brand new account. mint::decimals, mint::authority, and mint::freeze_authority tell it exactly how to initialize the Mint data. If the account already exists, the instruction fails — Anchor’s init protects against reinitialization attacks automatically.

The rent deposit for a Mint account is roughly 0.00144 SOL. Small, but real. You get it back when you close the account — though most Mints are never closed.

You can write this code in TypeScript too through the web3 library. Must try by creating your own mint!

Token Program

The System Program creates accounts. It does not care what those accounts mean. A freshly created 165-byte account is just bytes — it could hold anything. The Token Program is what gives certain accounts the specific meaning of holding a token balance.

The Token Program lives at TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA. That address looks like a typo but it isn’t — it is a legacy artifact from early Solana development that never changed because changing it would break every protocol on the network. Every wallet and every program that has ever touched a token knows this address.

Like the System Program, the Token Program ships with the validator and owns no state of its own. It is purely logic. All the state it manages lives in the Mint accounts and Token accounts it owns. The program itself is just a set of rules that govern how those accounts can be read and written.

Token-2022

There is a newer version called Token-2022, deployed at a different address: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb. It supports extensions the original Token Program never had — transfer fees, confidential transfers, interest-bearing tokens, permanent delegates, and more.

Most established tokens use the original. Newer projects increasingly reach for Token-2022. The core model is identical — extensions just layer optional behavior on top. If you are writing a program that accepts arbitrary tokens, you will eventually need to handle both. If you are building something new and control the mint yourself, Token-2022 is worth serious consideration.

The Token Account

With the System Program and Token Program in mind, the Token account itself is simple to understand. It is a 165-byte account, created by the System Program, owned by the Token Program, that holds your balance of one specific token.

One token account per token type. Your USDC balance lives in a different account than your BONK balance. Your BONK balance lives in a different account than your JUP balance. Every token gets its own dedicated account with its own address, its own rent deposit, and its own independent lifecycle.

This feels more verbose than Ethereum, where your ERC-20 balance is just a number in a mapping inside the contract. But it means every balance is an independent on-chain object. Any program can read it directly. Any protocol can verify your holdings without asking you. The state is open and composable in a way that private contract storage fundamentally is not.

pub struct TokenAccount {
    pub mint:             Pubkey,          // which token this holds
    pub owner:            Pubkey,          // who controls this account
    pub amount:           u64,             // balance in raw units
    pub delegate:         COption<Pubkey>, // approved spender
    pub state:            AccountState,    // Initialized, Frozen, Uninitialized
    pub is_native:        COption<u64>,    // wrapped SOL only
    pub delegated_amount: u64,             // how much delegate can spend
    pub close_authority:  COption<Pubkey>, // who can close this account
}

The Associated Token Account

You want to send USDC to a friend. In your bank app you type their email or phone number and the money arrives. The bank figures out the rest. On Solana, token balances don’t live in wallets — they live in token accounts, and token accounts have their own addresses separate from the wallet. So when you want to send someone USDC, which address do you send it to? Their wallet address can’t hold USDC directly. You need their USDC token account address specifically.

Now imagine every user has to manually create a token account for every token they want to receive, then share that address with anyone who might send them tokens. And every protocol, every DEX, every wallet app has to maintain a database mapping “Alice’s wallet → Alice’s USDC account → Alice’s BONK account → Alice’s JUP account.” That falls apart immediately. It does not scale, it is not reliable, and it puts an unreasonable burden on users just to receive tokens.

The Associated Token Account (ATA) is the solution. The idea is simple: instead of letting token accounts have arbitrary addresses, derive the address deterministically from two things the sender already knows — the recipient’s wallet and the token’s mint. Same inputs, same address, every time, for everyone.

How the Address Is Derived

An ATA address is a PDA — a Program Derived Address. If you have read the PDA section, you know a PDA is just a hash of some seeds combined with a program ID, where the result lands off the Ed25519 curve so no private key can exist for it.

For an ATA, the seeds are always exactly three things in this order:

seeds = [
    wallet_address,    // whose tokens
    token_program_id,  // always TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
    mint_address,      // which token
]
program = ATA_program_id  // AtsydnkFdNkFHuBWVEZDSWVdNgNpNjFNSELAVGMnAsrk

Feed those into the PDA derivation function and you get back one address. Always the same address. The ATA Program does not store a lookup table or maintain any database. It just re-derives the address on demand from the inputs.

Here is where it gets practical. When Yash sends USDC to Aryan for the first time:

1. Yash's wallet derives Aryan's ATA address
   (Aryan's wallet + USDC mint → one deterministic address)

2. Yash's wallet checks: does this account exist on-chain?

3. If no → Yash's wallet creates it in the same transaction
   Yash pays the 0.00203 SOL rent deposit
   Aryan's ATA now exists on-chain

4. The USDC transfer goes through
   Aryan's ATA balance goes from 0 to whatever Yash sent

Creating the YASH Token — How Everything Works Together

I want to create a token. I am going to call it YASH. It will have a fixed supply of one million tokens, six decimal places, and you will send some to a friend.

Simple enough goal. But to make it happen, four different programs need to coordinate, five different accounts need to exist, and each one has a job that none of the others can do. By the end of this you will not just know what each piece is — you will understand why removing any single one breaks the entire thing.

The Cast

Before the story starts, meet the players:

  • System Program — the only program that can create new accounts from nothing. Without it nothing else can exist.
  • Token Program — the program that understands what a token is. It owns Mint accounts and Token accounts and enforces every rule about balances and transfers.
  • ATA Program — the program that creates token accounts at predictable, deterministic addresses.
  • Your wallet — the keypair you hold. You are the authority behind everything that happens here.

And the accounts that will come into existence:

  • Mint account — the on-chain definition of the YASH token. What it is, how many decimals, who can create more.
  • Your token account — where your YASH balance lives. Not in your wallet — in a separate account specifically for YASH.
  • Your friend’s token account — where their YASH balance will live after you send them some.

None of these accounts exist yet. Let us build them one by one.

Step One — The Mint Account

The first thing Solana needs to know is: what is the YASH token? How many decimal places? Who has the right to mint new tokens? Who can freeze accounts? None of this exists anywhere yet. You need to create a Mint account.

Creating any account on Solana is a two-step process, always. First the System Program allocates the storage. Then the appropriate program initializes it with meaning.

For the Mint account, step one is asking the System Program to create an 82-byte account, transfer enough SOL for rent exemption — roughly 0.00144 SOL — and hand ownership to the Token Program. Step two is calling InitializeMint on the Token Program, which writes your settings into those 82 bytes.

Why does the System Program need to be involved at all? Because the Token Program can only modify accounts it already owns. It cannot create them from nothing. Only the System Program can do that. So you always go to the System Program first to allocate the account, assign it to the Token Program, then go to the Token Program to fill it with data.

You
 │
 ├──▶ System Program: create_account
 │         allocate 82 bytes
 │         deposit 0.00144 SOL
 │         assign owner = Token Program
 │         → Mint account now exists, empty
 │
 └──▶ Token Program: initialize_mint
           decimals = 6
           mint_authority = your wallet
           freeze_authority = your wallet
           → Mint account now has meaning

After these two instructions — which you can bundle into a single transaction — the YASH Mint account exists on-chain. Its address is whatever keypair you generated for it. The total supply is zero. Nobody holds any YASH yet.

Step Two — Your Token Account

The Mint exists but your wallet cannot hold YASH directly. Your wallet is owned by the System Program. The System Program knows nothing about tokens — it only understands SOL. To hold YASH, you need a Token account.

A Token account is a separate 165-byte account, owned by the Token Program, that holds your balance of one specific token. You need one for YASH specifically. It will sit at its own address on-chain, completely separate from your wallet.

You could create a token account at a random keypair address. But then nobody would know where to find your YASH balance — they would have to ask you every time. Instead you create an Associated Token Account — a token account at a deterministic address derived from your wallet and the YASH mint. Anyone who knows your wallet address and the YASH mint address can compute exactly where your YASH lives.

Creating your ATA involves three programs working in sequence. The ATA Program orchestrates it, the System Program allocates the storage, and the Token Program initializes the token account data.

You
 │
 └──▶ ATA Program: create_associated_token_account
           derives address from (your wallet + YASH mint)
           │
           ├──▶ System Program: create_account
           │         allocate 165 bytes
           │         deposit 0.00203 SOL
           │         assign owner = Token Program
           │
           └──▶ Token Program: initialize_account
                     mint = YASH mint address
                     owner = your wallet
                     amount = 0
                     → Your ATA exists with zero balance

Step Three — Minting Tokens Into Existence

Now you have a Mint account defining what YASH is, and a token account ready to hold it. But supply is still zero. Time to actually create some YASH.

You call MintTo on the Token Program. You pass it the Mint account, your ATA as the destination, and sign with your wallet — which holds the mint authority. The Token Program checks your signature against the mint_authority field in the Mint account. They match. It creates one million YASH tokens directly into your ATA.

Two things change simultaneously. The Mint account’s supply field goes from 0 to 1,000,000,000,000 raw units — one million YASH at six decimals. Your ATA’s amount field goes from 0 to 1,000,000,000,000. These two numbers are always kept in sync by the Token Program. You cannot credit a token account without the mint supply reflecting it.

At this point you have one million YASH sitting in your ATA. The Mint account shows a supply of one million. Nobody else holds any.

Now lock the supply. If you revoke the mint authority — setting it to None — nobody, including you, can ever mint more YASH.

One instruction, permanently verifiable on-chain. Anyone can look up the YASH Mint account and see mint_authority: None. The supply is fixed at one million forever.

Step Four — Sending YASH to Your Friend

You want to send 1,000 YASH to your friend. Their wallet address is public — you have it. But they have never held YASH before, so their ATA does not exist yet.

Your wallet derives their ATA address from their wallet and the YASH mint. You check on-chain — the account does not exist. Your transaction creates it first, then transfers. You pay the 0.00203 SOL rent deposit for their ATA. Small cost, but it comes out of your wallet.

You
 │
 ├── derive friend's ATA address
 │   (friend's wallet + YASH mint → deterministic address)
 │
 ├──▶ ATA Program: create friend's ATA  (if it doesn't exist)
 │         System Program allocates 165 bytes
 │         Token Program initializes with friend's wallet as owner
 │         friend's ATA balance = 0
 │
 └──▶ Token Program: transfer
           from:      your ATA
           to:        friend's ATA
           authority: your wallet (you sign)
           amount:    1,000 * 10^6 raw units

The Token Program verifies: your ATA and your friend’s ATA both reference the same YASH mint. Your balance is sufficient. You actually signed. Neither account is frozen. All checks pass. Your ATA goes from 1,000,000 to 999,000 YASH. Your friend’s ATA goes from 0 to 1,000 YASH. The mint supply is unchanged — this is a transfer, not a mint.

Why You Cannot Remove Any Piece

Here is the question the whole story was building to. You needed four programs and five accounts. Why not fewer?

Why not skip the System Program and let the Token Program create accounts directly?

The Token Program is designed to manage token state — balances, authorities, supply. If it could also create arbitrary accounts, it would have unbounded power over the entire network’s storage. The System Program exists as the single gatekeeper for account creation precisely so that power is controlled and auditable. Every program on Solana has a narrow job. The System Program’s job is allocation. Nothing else does it.

Why not put your balance directly in your wallet instead of a separate Token account?

Your wallet is owned by the System Program. The System Program knows nothing about tokens — it only understands lamports. For the Token Program to enforce token rules — checking mints match, checking authorities, enforcing freeze status, tracking delegations — it needs to own the accounts storing token balances. Ownership is what gives it write access. If your token balance lived in your wallet, the Token Program could not touch it.

Why not skip the ATA Program and just use regular token accounts?

You could. Token accounts at random keypair addresses are valid. But then every wallet, every protocol, every DEX would need a separate database mapping wallets to their token accounts for every possible token. The ATA Program exists to make that coordination unnecessary. It establishes a universal standard: given a wallet and a mint, the token account address is always this specific derivation. One convention, followed by everyone, eliminates an entire class of infrastructure complexity.

Why does the Mint account need to exist at all? Why not store supply inside each token account?

Because supply is a global property of the token, not a property of any individual holder. If supply were stored across token accounts, minting would require updating every account simultaneously — impossible in a parallel system. The Mint account is the single source of truth for what the token is and how much of it exists. Every token account references it. Every transfer validates against it. It is the anchor point the entire system coordinates around.

The YASH Token Ecosystem

YASH TOKEN ECOSYSTEM
─────────────────────────────────────────────────────────

  System Program          Token Program          ATA Program
  (creates accounts)      (manages tokens)       (derives addresses)
       │                        │                      │
       │                        │                      │
       ▼                        ▼                      ▼

  ┌─────────────┐      ┌──────────────────┐    ┌──────────────────┐
  │ MINT ACCOUNT│◀─────│  Token Program   │    │  Your ATA        │
  │             │      │  owns this       │    │  derived from    │
  │ supply: 1M  │      └──────────────────┘    │  (you + mint)    │
  │ decimals: 6 │               │              │  amount: 999,000 │
  │ auth: None  │               │              └──────────────────┘
  └─────────────┘               │
        ▲                       │              ┌──────────────────┐
        │                       │              │  Friend's ATA    │
        │ both reference        │              │  derived from    │
        │ same mint             │              │  (friend + mint) │
        │                       │              │  amount: 1,000   │
        └───────────────────────┘              └──────────────────┘

  PROGRAMS              ROLE                   CAN IT BE REMOVED?
  ──────────────────────────────────────────────────────────────
  System Program        Creates all accounts   No - nothing else can
  Token Program         Enforces token rules   No - nobody else owns accounts
  ATA Program           Derives addresses      Technically yes, practically no

Four programs. Five accounts. Each one doing exactly one thing that no other component can do. That is not accidental complexity — it is the account model working as designed. Separation of concerns, enforced at the protocol level, making every piece independently auditable, composable, and replaceable without touching anything else.

Program Derived Addresses and the Bump Seed

Every account on Solana has an address. For your wallet, that address comes from a keypair — a private key and a public key generated together. You hold the private key, and the public key becomes your address. When you sign a transaction, you are proving to the network that you hold the private key behind that public address. That proof is what gives you the right to spend SOL, transfer tokens, or authorize any action tied to your wallet.

This works perfectly for humans. Humans can hold private keys.

Programs cannot.

A program deployed on Solana has no private key. It is just code sitting at an address. It cannot sign anything. But programs frequently need to own accounts — a vault holding escrowed funds, a treasury storing a protocol’s reserves, a state account that only the program itself should be able to modify. If owning an account requires signing for it, and programs cannot sign, how does a program ever control anything?

This is the exact problem Program Derived Addresses (PDAs) solve.

What a PDA Is

A PDA is an account address that was not generated from a keypair. Instead it was computed — derived mathematically from a combination of seeds you choose and the program’s own ID. No private key was ever involved. No private key exists for it. Nobody in the world can sign for a PDA the way a wallet signs for its address.

But the program that derived it can authorize actions on its behalf through a mechanism the runtime provides. That mechanism is invoke_signed, and it is what makes PDAs genuinely powerful rather than just an interesting curiosity.

Before getting to signing, you need to understand the derivation itself — because the derivation is what everything else is built on.

How a PDA Is Derived

The derivation takes three inputs: your seeds, your program ID, and a number called the bump. It hashes them together and produces a 32-byte address.

PDA = hash(seeds + program_id + bump)

Seeds are whatever you choose — a static string like b"vault", a user’s public key, an order ID, a mint address. They are the inputs that make each PDA unique and meaningful.

The program ID is fixed — it is the address of your deployed program.

The bump is the piece that requires explanation.

The Bump — Why It Exists

Solana’s keypairs use a cryptographic system called Ed25519. Every valid public key in this system is a point on a specific mathematical curve — the Ed25519 curve. The curve has a precise shape, and every point that lies on it has a corresponding private key somewhere.

This creates a problem. If you hash your seeds and program ID together and the result happens to land on the Ed25519 curve, then a private key theoretically exists for that address. Someone could potentially find it and sign for your PDA as if they were a normal wallet. The entire security model collapses.

So Solana adds a requirement: a PDA must be an off-curve point. The hash result must not lie on the Ed25519 curve. If it does, it is not a valid PDA.

The bump is how you push the result off the curve. It is a single number, starting at 255, that gets appended to your seeds before hashing. If the hash of your seeds plus 255 lands on the curve, you try 254. Then 253. Then 252. You keep decrementing until the result lands off the curve. That first value that produces a valid off-curve address is the canonical bump.

Thanks to #mlh fro their solana

EFES-2026 Tatbikatı'nda nefes kesen gece safhası

Türkiye’nin ev sahipliğinde düzenlenen EFES-2026 Birleşik, Müşterek, Fiili Atışlı Arazi Tatbikatı’nın Seçkin Gözlemci Günü gece safhasında, topçu ve havan atışlarıyla desteklenen amfibi harekatı gerçekleştirildi. Tatbikatta yapay zeka destekli sistemler kullanılırken, 50 ülkeden 10 binden fazla personel yer aldı.

EFES-2026 Tatbikatı'nın Gece Safhası Nefes Kesti

Türkiye’nin ev sahipliğinde Ege Ordusu Komutanlığı sevk ve idaresinde düzenlenen EFES-2026 Birleşik, Müşterek, Fiili Atışlı Arazi Tatbikatı’nın Seçkin Gözlemci Günü gece safhasında, topçu ve havan atışlarıyla desteklenen amfibi harekatı icra edildi; hedefler kara, deniz ve hava unsurlarınca imha edildi. Tatbikata 50 ülkeden 10 binden fazla personel katıldı, ilk kez simülasyon destekli komuta yeri safhası 24 saat esasına göre yapıldı.