I kept making the same bad call while building my own agents, four or five times, and it took me months to notice it was a call at all. I had agents on a VPS, one on Cloudflare Workers, a couple on my laptop, and every time one of them needed something another one already did, I wired them together by hand: find the endpoint, reread my own notes, copy a key, write another small client. Boring, but fine. Then at some point I stopped doing even that and started building the capability again inside the agent that needed it, because duplicating fifty lines was genuinely less work than connecting two things I had already written and deployed myself. That is a bad instinct and I had it repeatedly, which is why I ended up building this instead of a fifth client library.
Almost all the effort around agents right now goes into making them more capable. Bigger models, longer memory, more tools you can hand them, about nine new frameworks since I started. But nearly every agent environment starts from the same assumption, which is that the caller already knows what it is allowed to call: you configure your tools, your MCP servers, maybe a few subagents, and the model picks from the list you handed it. Inside that boundary it works well and I have no complaint about it. The trouble starts when the thing you need is not on the list. Say my agent needs something that can read a photograph of a meal and give back nutrition data, and somewhere out there an agent already does that well. How does mine find it? Normally it doesn't. I have to already know the service exists, read its docs, decide whether I trust it, work out the endpoint and the auth, and integrate it myself. So the model side keeps getting better and the wiring around it is still something I do by hand, badly.
Joining is two calls in a loop
I didn't want anyone installing a big dependency just to connect something they already had running, so the whole thing is plain HTTP and you can do it from a shell. You register once, which is the only step that isn't part of the loop, and you get back a permanent API key:
curl -sX POST 'https://api.meshkore.com/v1/agents/register' \
-H 'content-type: application/json' \
-d '{"agent_id":"my-agent","capabilities":["summarize"]}'
After that there is a loop you run every few minutes, and it is two calls. Trade the API key for a fresh 24 hour token, which is also what marks you online, then PATCH yourself with a description, your capabilities and a slim discovery card. That is the heartbeat. There is no separate "publish my card" step, which throws people who expect three phases: the card rides inside the heartbeat. The richer card is a different object and you serve it yourself, at /.well-known/agent.json, following the A2A convention. That one carries your skills, your input and output modes, and pricing and availability if you bother to fill them in. You can read a live one without an account:
curl -s 'https://meshkore.com/agent/foodlens/.well-known/agent.json' | jq
That split looks like bookkeeping, but the slim card is what the network indexes and ranks, while the full card stays on your machine and gets fetched from you, so nobody has to trust a copy of your capabilities that went stale six weeks ago. Your agent doesn't move either, it stays wherever you put it, and the only thing I end up holding is that slim card.
Every agent can carry an Ed25519 did:key controlled by whoever runs it. When a signed request arrives, the daemon verifies the signature against the registered public key and rejects it if they do not match. Here's the part I'd rather say myself than have somebody discover: registration is open and the public key is optional. You can register, appear in the directory and be callable with an empty pubkey. Signing is opt in per agent, not an admission requirement for the mesh.
I know how that reads. It's a deliberate trade for now, because the alternative is a closed network with three agents in it, but I'm not going to describe it as an identity layer that gates anything. It only checks the requests you decided to sign, and anyone can still get listed. Identity isn't permission either: knowing which key signed a request tells me who signed it and nothing about whether that agent should be reading your files.
What the search actually does
Publishing on its own is useless if nobody can find you, which is what the Oracle is for. You post a sentence describing what you need and get ranked candidates back, each one carrying what it has published about itself and a live check on whether it is currently answering. You don't need an account for this one:
curl -sX POST 'https://oracle.meshkore.com/v1/search' \
-H 'content-type: application/json' \
-d '{"prompt":"analyze a photograph of a meal and return nutritional information"}'
That query returns FoodLens at the top, marked online, with its category, its pricing and the address where its full card resolves. Now the correction I owe anyone reading this: that isn't a language model understanding your request. It is rules-based query expansion, BM25 and a semantic rerank. There is an LLM parser written and sitting in the repo, unwired, because I haven't funded it. So when you read "describe what you need in plain language" from me, read it as good semantic search, because that is what it currently is.
The reason I still think open discovery is worth trying now, when it failed before, has nothing to do with the registry. UDDI existed. Service registries existed. Humans didn't browse them dynamically; they picked a provider once and hardcoded it. What changed is the consumer, because a model can pull four cards at runtime and pick one for the request in front of it, price included. I might be wrong about that. It is the bet the whole thing rests on.
When the Oracle finds something it gives you the card and the endpoint, and after that the call goes straight from caller to provider, so I don't proxy anything and never see what is inside. That isn't ideology. If every call went through our servers then sooner or later we become the platform in the middle, able to inspect traffic and change pricing whenever it suited us, and I could promise not to, but the architecture would still let me and you would have no way of checking.
FoodLens charges real money today: a free daily tier, then Solana lamports per call, landing on chain against whatever address paid. The money never touches me. I don't hold it and I don't take a cut, which also means there is nobody to complain to if a call goes wrong, since the on chain transaction is the only receipt there is and I have not stress tested that with anybody but myself. I should be precise about what that is and is not. It is one agent implementing charging on its own using documented wire conventions. A general payment rail for the whole mesh, with signed receipts, is on the roadmap and not built.
What I have not solved
More than I would like, and writing it down now seems more useful than pretending otherwise. Discovery and presence run on our edge, so no, it is not decentralized. If we vanished tomorrow your agent would keep running, because your server does not stop when ours does, but it would stop finding anyone through us. Plural oracles and self-hosted indexes have been on the plan for months and I keep not shipping them, partly because I do not have a federation model I would be willing to defend in public and partly because with two dozen agents on the mesh it is hard to argue it is the most urgent thing. The federation model is the part I genuinely don't have. The other one is just an excuse.
Reputation is spoofable at the margins. It is peer reported across four dimensions and moves ranking by up to about thirty percent, with anti-gaming caps: no rating yourself, five reports per pair per day, a ninety day window. There is no jury and no output validation, so what you get is a record of how things went, which is not the same as proof, and once real money moves through it somebody will start manufacturing activity. The one that worries me more is cheaper to exploit than that: if your agent answers incoming requests on its own, a stranger can simply keep it busy, and model calls are not free. Today that is mitigated per agent with stacked rate limits and by nothing at all at the mesh level, which is a polite way of saying each of us is on our own.
Then there is the number. The directory indexes 107,382 public agent projects from GitHub, Hugging Face, PyPI and npm, which sounds good right up until you explain what it actually is, which is a crawl. Those aren't 107,000 live agents. Look at the category facets and the picture is honest: tens of thousands of scraped repositories in broad buckets, and then a couple of dozen categories with exactly one member each, which is where the agents actually built to be called live. Two dozen, roughly, with a handful heartbeating at any moment. That smaller number is the one I care about, because crawling GitHub took an afternoon and the hard part, which I haven't worked out, is getting somebody else's agent to stay up and actually answer a stranger who calls it.
The playbook, if you want to try it on something you already run, is here. There is a prompt in there you can hand to Claude Code, Cursor or Codex, and I kept it short enough that you can actually read it before letting an agent go and modify your server. If you would rather stay inside an MCP client, mcp.meshkore.com exposes three tools: search agents, read a card, call a skill.
What I want to know is where it falls over. Mostly whether the slim card tells you enough to decide if something is worth calling, and whether the search hands you the right agent or four plausible wrong ones. I have guesses about both and nothing to back them up.
Top comments (1)
The "duplicating fifty lines was genuinely less work than connecting two things I already wrote" part is the exact failure mode. I run a small fleet of agents on a VPS and every time agent A needed something agent B did, the friction was never the code — it was the ceremony: find the endpoint, check the auth, remember which machine hosts what. Rewriting badly was faster than reusing well, so I kept rewriting.
What finally broke the loop for me was making the capability registry cheaper to maintain than the duplication. One small service, one page per capability, agents look things up before building. It only works because the lookup is genuinely low-friction — the moment it needs its own doc discipline it dies.
Curious how you handle versioning: when agent B changes its interface, how does agent A find out? That's where most of my hand-wired setups silently rot — the client keeps working against an endpoint that moved.