Sign in

Rocky Lhotka 🤘🖖

@rockylhotka.fosstodon.org.ap.brid.gy
402 followers 4 following 198 posts

🧑 he/him 🧑‍💻 Open-source creator (#cslanet, #rockbot, and more) 🤵 VP of Strategy @ Xebia; Chief Software Architect @ Marimer LLC 🎗️ #MicrosoftMVP and RD […] 🌉 bridged from ⁂ fosstodon.org/@rockylhotka, follow @ap.brid.gy to interact

PostsRepliesMedia
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 25/09/2026
A key lesson I've learned for using #ai to build software is to also build the tools so the agent can "close the loop" and validate its own work. That is a powerful accelerator, and a way to avoid having the agent go "off the rails" as it works. blog.lhotka.net/2026/09/25/C...
blog.lhotka.net
Closing the Loop
VP, Open Source Creator, Author, Speaker
123
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 21/09/2026
Using #claudecode as a remote control _server_ makes working with #ai really nice! blog.lhotka.net/2026/09/21/Remote-C…
010
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 19/09/2026
First in some posts about using Claude Code remotely SSH Is Not a Desktop blog.lhotka.net/2026/09/18/SSH-Is-N… #ai #claude
blog.lhotka.net
SSH Is Not a Desktop
I work across three physical PCs. Two of them (I’ll call them `devbox1` and `devbox2`) are powerful desktop machines that sit in my office and run all the time. The third is my laptop, which goes with me when I travel. These days most of my development work is done through Claude Code. When I’m away from the office, I really don’t want to run Claude Code on my laptop. I want it running on one of the desktop machines, and I want the laptop to just be a way to talk to it. This is the first in a series of posts about how I’ve approached that problem. I started with SSH, which is what this post is about. ## Why Remote In at All? You might wonder why I don’t just run Claude Code on the laptop. There are two reasons. First, my laptop doesn’t have all my tools. The desktop machines have everything installed and configured: Docker, kubectl with access to my Kubernetes cluster, multiple .NET SDKs, database tools, and all my repos checked out at the same paths. Claude Code can only use the tools that exist on the machine where it is running. On the laptop some of those tools are missing, or aren’t configured, and Claude ends up stuck or trying to work around what it doesn’t have. I _could_ try to keep the laptop in sync with the desktops, but that is a lot of ongoing work for a machine that I want to keep light and simple. Second, and this one surprised me a bit, Claude Code uses a lot of bandwidth. Every time you interact with Claude, it sends the context (the conversation so far, files it has read, output from tools, and so on) up to the model, and then streams the response back. In a long session working on a real codebase that adds up to a lot of data - and a lot of it is _upload_ , which is usually the weakest part of any network connection. > ℹ️ I travel quite a bit, and airplane wifi and hotel wifi are often terrible. Running Claude Code locally on a bad connection goes from slow to basically unusable. An SSH session, on the other hand, only sends keystrokes and terminal text back and forth. If Claude is running on my desktop machine, all the heavy traffic goes over my office internet connection, and the only thing going over the hotel wifi is what’s on my screen. That’s a _much_ better experience. So the plan was simple. Windows has had an OpenSSH server for years, and from my laptop it is one command to get a shell on either desktop machine. `ssh devbox1`, `cd` into a repo, run `claude`, and get to work. That mostly works. But I’ve run into four problems that have cost me a lot more time than I expected. The common thread is that an SSH session is _not_ the same as being logged into the desktop, and Claude Code (and the tools it uses, like `git`, `gh`, and Docker) often assume that it is. ## Problem 1: Disconnecting Kills Claude The first problem I hit is that if I close the terminal on my laptop, or the laptop goes to sleep, or the wifi drops, whatever I was running on the remote machine dies. From the SSH server’s perspective this is reasonable behavior. On Windows, the OpenSSH server runs everything started in a session inside a Windows job object, and when the session ends the job is torn down - along with every process in it. Running something in the background doesn’t help, and neither does `Start-Process`. If the process was started from that SSH session, it dies when the session ends. For a quick `git status` that’s no big deal. For a Claude Code session that’s 20 minutes into a refactor, it is painful. Claude is killed in the middle of whatever it was doing, and the code is left in whatever state it happened to be in when the connection dropped. On Linux the answer to this is `tmux` or `screen`, which let you run things inside a terminal session that isn’t tied to your SSH connection, so you can reconnect later. Windows doesn’t really have an equivalent. You can use WSL to get there, but a lot of my work is Windows-specific (.NET, PowerShell, Windows paths), so that’s only a partial answer. Claude Code does help a little. After reconnecting, I can run `claude --resume` and pick up the conversation. But that only restores the _conversation_. If Claude was in the middle of a build, or a test run, or halfway through a set of edits, that work was interrupted, and I have to figure out where things were before I can continue. And because the whole reason I’m doing this is a bad network connection, this happens a lot. This is the problem that eventually pushed me beyond plain SSH, and I’ll write about that in future posts. ## Problem 2: Git and gh Need Different Authentication The second problem showed up the first time Claude tried to push a branch to GitHub. On a normal Windows dev machine, Git is set up to use Git Credential Manager (GCM). GCM works great. It pops up a browser or dialog, you sign into GitHub, and it caches a token so you never have to think about it again. The thing is, in an SSH session there is nothing to pop up _on_. GCM needs either a GUI or an interactive terminal to prompt you, and when it has neither you get this very unhelpful error: unable to read askpass response could not read Username for 'https://github.com' This also applies to the commands Claude Code runs, because those aren’t interactive either. So a credential setup that works perfectly when I’m sitting at the machine fails when I’m connected over SSH. My solution was to stop using HTTPS for Git on these machines and switch to SSH keys for GitHub: 1. Create a dedicated GitHub key, `~/.ssh/id_ed25519_github`, with _no passphrase_. That’s on purpose. A passphrase means using `ssh-agent`, and an agent started in my desktop session isn’t available to an SSH login - which gets you right back to the same kind of failure. 2. Add an entry to `~/.ssh/config` that ties that key to `github.com` with `IdentitiesOnly yes`. Without that, ssh tries my _other_ key first (the one I use to connect between my machines). GitHub rejects it, and after enough rejected keys you get “Too many authentication failures” and nothing works. 3. Set up a global URL rewrite so every repo uses SSH, no matter how it was cloned: git config --global url."git@github.com:".insteadOf "https://github.com/" > ⚠️ One gotcha with that last step: `git remote -v` still _shows_ the https URL, because the rewrite happens when git actually talks to GitHub. If you want to see what’s really going to be used, run `git ls-remote --get-url <url>`. The `gh` CLI is a separate story, because it doesn’t use Git’s credentials at all. It stores its own token, and by default it puts that token in the Windows credential store. That works fine at the desktop, but I’ve had `gh` tell me its token is invalid over SSH when it was working fine at the console. If you run into that, `gh auth login --insecure-storage` writes the token to a plain file (`%APPDATA%\GitHub CLI\hosts.yml`) that any shell can read. As the name of the flag implies, that is a security tradeoff, so think about it before you do it. It is also worth knowing that the GitHub MCP server authenticates separately from both Git and `gh`. At one point when `gh` wasn’t working over SSH, Claude could still read issues and create PRs through the MCP server, which kept me going while I sorted out the CLI. ## Problem 3: Reboots Leave Things Half-Started My desktop machines are “always on” - until they aren’t. Patch Tuesday comes around, Windows Update decides to reboot overnight, and the machine comes back up sitting at the login screen with nobody logged in. The OpenSSH server runs as a Windows service, so I can still connect and start Claude. But a lot of what Claude needs to do real work doesn’t start until someone logs in. Docker Desktop is the big one. Even though it installs some Windows services, Docker Desktop is really a per-user app that starts when you log into the desktop. No login, no Docker. The same is true for anything else that starts from the Startup folder or a “run at login” setting. From an SSH session this is confusing. I connect, start Claude, and everything seems normal until Claude tries to build a container or run tests that need one. Then it fails with an error saying it can’t connect to the Docker engine. And I can’t really fix it from SSH. Starting Docker Desktop from an SSH session either doesn’t work, or it starts inside the SSH session’s job and dies when I disconnect (see Problem 1). What I end up doing is connecting with a GUI remote desktop tool, logging in so all the normal startup apps run, waiting for Docker to be ready, and then going back to SSH and Claude. > ℹ️ I could set the machines to log in automatically, and that would solve this problem. But that means leaving a logged-in desktop sitting there, and I’d rather not do that. ## Problem 4: Sometimes You Just Need the GUI This is the one I find most frustrating, because it kind of defeats the purpose of using SSH in the first place. A lot of authentication and troubleshooting on Windows assumes someone is sitting at the machine: * Signing into GitHub (or Azure, or Claude) for the first time usually means a browser-based login * Windows Hello, UAC prompts, and “allow this app?” dialogs show up on the physical desktop, not in my SSH terminal * Credential stores are often tied to the interactive login session, so a token you set up at the desktop may not work from SSH, and vice versa * After a reboot, apps like Docker Desktop don’t start until someone logs in * When something fails over SSH, the most useful question is often “does it work when I’m actually logged in?” - and you can’t answer that from SSH So in practice, getting SSH to work, and fixing it when it breaks, often means using AnyDesk or RustDesk to connect to the _same_ machine with a GUI. I log into the desktop, complete the browser login or click through the prompt, make sure the tool works there, and then go back to SSH to see if it works there too. It works, but it is clunky. I’m using a GUI remote desktop tool to fix problems with my command line remote session! Over time, my approach has been the same as with the Git problem. For each tool, find a way to authenticate that doesn’t depend on being logged into the desktop, and set it up once while I’m at the GUI. SSH keys instead of GCM. File-based tokens where the risk is acceptable. Services that start at boot instead of at login. Every tool I move over is one less reason to fire up AnyDesk. ## A Productivity Tip: Review Changes Through a Branch This isn’t really a problem, but it is something I’ve found very helpful, and it applies no matter how you connect to Claude on another machine. When Claude is running on a different machine, the changes it makes are on that machine too. You can review them by scrolling through `git diff` in the terminal, but over a slow connection that’s not a great experience - especially for anything bigger than a few lines. So I have Claude do its work in a git branch and push that branch to GitHub, usually with a pull request. Then I can review the changes on my laptop the same way I’d review anyone else’s code, in the browser using GitHub’s diff view. If I want to run or debug the code locally, I can pull the branch down to the laptop. This post is an example! Claude helped me draft it on `devbox1` while I was working from my laptop. When I wanted to read the draft, I asked Claude to create a PR, and I read it on GitHub from my laptop. My feedback went back to Claude, and each change it pushed updated the same PR. This also has another benefit. Work that only exists on the remote machine isn’t backed up anywhere until it’s pushed. If the session dies or the machine reboots, having a pushed branch means nothing is lost. ## Conclusion If you are thinking about using SSH to connect to a Windows machine so you can run Claude Code there, here’s what I’ve learned: 1. Disconnecting will kill your Claude session. On Windows anything started in an SSH session dies when the session ends. `claude --resume` brings back the conversation, but not the work that was interrupted. 2. Nothing can prompt you for credentials. Any login that pops up a dialog, opens a browser, or asks for a passphrase will fail over SSH. Set up credentials that don’t need to prompt. 3. Know what needs a desktop login. After a reboot, anything that starts at login (like Docker Desktop) won’t be running. If Claude hits a strange error after Patch Tuesday, check that first. 4. Keep a GUI option available. You’ll still need a real desktop session now and then, so have AnyDesk, RustDesk, or RDP set up _before_ you need it. 5. Review changes through a branch. Have Claude push its work to GitHub so you can review it from anywhere, and so the work isn’t only on the remote machine. None of these problems are hard once you understand them. What makes them hard is that the error messages almost never say “this is failing because nobody is logged into the desktop.” Once I started asking “is this running in a desktop session or not?” as my first troubleshooting question, most of the mystery went away. Even with these issues, running Claude Code on a well-equipped desktop machine and connecting over SSH is worth it. I get all my tools from anywhere, and a bad airplane connection is annoying instead of a showstopper. SSH was my first step though, not my last. In my next post I’ll talk about Claude Code’s Remote Control feature, which keeps the session running on the desktop machine and lets me connect to it from my laptop, a browser, or my phone. After that I’ll talk about going a step further and running a Remote Control _server_ that’s always available, even when nobody is logged in.
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 30/08/2026
This is why I have had so much fun creating #rockbot: building a good harness is challenging thenewstack.io/building-ai-agent-ha…
thenewstack.io
Your AI agent is only as good as the harness around it
Build production-ready AI agents with effective guardrails, tool contracts, permissions, and tracing systems beyond simple demos.
010
Reposted by Rocky Lhotka 🤘🖖
Miguel de Icaza ᯅ🍉 @migueldeicaza.mastodon.social.ap.brid.gy · 11/08/2026
For more than twenty years, I have faithfully maintained and published a PGP key, ensuring that journalists, dissidents, intelligence agencies, or anyone else with sufficiently sensitive information could establish a secure channel directly to me, and as far as I can tell, not one person has […]
mastodon.social
Original post on mastodon.social
407
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 11/08/2026
Spelling errors are the new indicator of content created by humans. *Intentionally* adding just one spelling error in a document or blog post helps reinforce that it was authored by a human 😀
010
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 26/07/2026
Adding union support to the #cslanet CslaGeneratorSerialization. www.youtube.com/watch?v=Q6s1CQf6qNA
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 21/07/2026
youtu.be/ZRoLZ8Wwn8Y?si=GMpBvV0Y0tQ… AI is changing how we build, let's get past the hype. I'm speaking @ #VSLive! San Diego (Sept 14–18) on #ai and #blazor Learn more at: vslive.com/sandiego Save $500 when you register with my discount code: LHOTKA […]
fosstodon.org
Original post on fosstodon.org
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 21/07/2026
Headless agents are a key part of any #agentic #ai solution blog.lhotka.net/2026/07/20/Headless…
blog.lhotka.net
Headless Agents
When most people talk about AI agents, they picture a chat interface: a human types something, and the agent responds. That’s a real and useful thing. But it’s also only a small corner of the agent landscape. There’s another category of agent — one that has no chat interface at all. No human types a prompt. No human reads the output. The agent wakes up in response to some event, does its work, and disappears. I call these _headless agents_ , and I think they’re going to be far more common in business and enterprise settings than their chat-facing counterparts. ## What Triggers a Headless Agent? A chat agent is triggered by a human’s input. A headless agent is triggered by _something else_. That “something else” is the interesting part: * A new row is inserted into a database table * A record is updated and crosses some threshold * A message arrives in a queue * A file lands in a storage container * A scheduled timer fires * An API webhook delivers an event * Another agent hands off a task In each of these cases, the agent wakes up, examines the situation, applies some judgement, takes some actions, and shuts down. No human in the loop. No chat window. No one watching in real time. That’s a headless agent. ## Why These Will Dominate in Enterprise Think about the actual day-to-day work that happens in most business roles. Plenty of it is genuinely interesting and requires human creativity, empathy, and deep domain expertise. But some significant fraction of it is… not. How many people have a valuable job, but _also_ need to check a specific inbox every morning and route some emails? Or stop their real work a few times a day to fill out some paperwork, send some notifications, or update a spreadsheet that feeds into some downstream process? These tasks often require _limited, but some_ judgement. Enough that a hard-coded rule engine tends to fail. Not enough that they couldn’t be handled by an agent with a well-crafted directive and access to the right tools and data. These are the low-hanging fruit of AI automation. Not replacing people’s _entire_ jobs — replacing the repetitive, peripheral tasks that orbit around people’s actual work. The tasks that fragment focus, consume time, and produce nothing that requires a human. In my view, _this_ is where agents will have the most immediate and measurable impact in business and enterprise settings. And these are all headless agents. ## Same Architecture, Different Trigger A headless agent is still an agent. As I’ve described before, every agent is: > **Agent = Harness + LLM + Directive** The Harness is the code that orchestrates everything — the loop, the tool calls, the context management. The Directive is the system prompt that shapes the agent’s behavior and scope. The LLM does the reasoning. For a chat agent, the Harness receives user input and returns a response to a UI. For a headless agent, the Harness receives an event — a queue message, a database notification, a webhook payload — and acts on it. Structurally, these are the same thing. The difference is what initiates the work and what happens with the result. A headless agent’s Directive is often _narrower_ than a chat agent’s. It doesn’t need to handle arbitrary conversational context. It has a specific job: when this kind of event arrives, here is how to handle it. That narrowness is actually a feature. A tightly scoped Directive means the agent is more predictable, more testable, and less likely to go off in unexpected directions. ## Headless Agents Absolutely Require Observability This is not optional. With a chat agent, there’s a human in the loop. If the agent produces bad output, the human notices. They can ask a follow-up question, try again, or escalate. The human is the safety net. With a headless agent, there is no human watching. Nobody sees the output until some downstream consequence reveals that something went wrong — maybe days or weeks later, maybe never in a way that’s attributable to the agent. I’ve written about observability for RockBot, and everything I said there applies here — _with even higher stakes_. For headless agents, you need: * **Structured logging for every invocation.** What event triggered the agent? What did it do? What tools did it call? What was the final output? * **Metrics on token consumption and cost.** Headless agents can run at high volume. A bad prompt that causes looping or excessive LLM calls can silently burn budget before anyone notices. * **Latency tracking.** If an agent is supposed to process events in near-real-time but its p95 latency is climbing, something is wrong with the pipeline. * **Failure alerting.** If the agent fails to process an event — or processes it incorrectly — someone needs to know. Not eventually. Now. Without these things, you’re running automation that nobody can see, that nobody can debug, and that nobody will notice is broken until the damage is already done. That’s not automation — that’s a time bomb. The rule I’d apply: if a human used to do this task and would have noticed when something went wrong, your headless agent needs to be able to surface that same signal through instrumentation. ## Where Headless Agents Run Headless agents are event-driven by nature, which makes them a natural fit for event-driven infrastructure. Azure Functions are an obvious choice. A Function can be triggered by a queue message, a database change, a blob arriving in storage, a timer, an HTTP call — basically everything on the list above. The Function runs, does its work, and shuts down. You pay for what you use, not for idle time. KEDA (Kubernetes Event-Driven Autoscaling) is another option, particularly if you’re already running on Kubernetes. KEDA can scale your agent workloads to zero when there’s nothing to process, and back up when events start arriving. The same economic principle: no idle resource cost. Other event-driven platforms — AWS Lambda, Google Cloud Run, and similar — all apply the same model. The key property all of these share is that the agent doesn’t sit idle waiting for work. It responds to demand. This matters because the “running cost” of a headless agent that processes 10 events a day is dramatically different from a long-lived service that holds a connection open around the clock. ## Headless Agents Are Still Connected Being headless doesn’t mean being isolated. These agents use the same ecosystem as any other agent. A headless agent can call MCP servers to query databases, update records, send notifications, call external APIs, or retrieve documents. It can use A2A (agent-to-agent) protocols to delegate sub-tasks to specialized agents. It can enqueue messages to downstream systems or other agents as part of its processing. In a mature enterprise agent ecosystem, you’d expect to see headless agents passing work to each other via queues — one agent processes an incoming order event, enriches the data, and publishes a message that triggers another agent to run a credit check, which in turn triggers another agent to update inventory. Each agent has a clear, bounded responsibility. Each can be deployed, scaled, and monitored independently. This is the agentic equivalent of a well-designed microservices architecture: loosely coupled, independently deployable, observable at every boundary. ## Where This Is Headed I have no doubt that headless agents will quietly become the most important category of AI deployment in business. Not because they’re flashy — they’re the opposite of flashy — but because they’re where the actual automation happens. Chat agents are visible and immediate. They’re easy to demo and easy to understand. But the work that changes how a business operates happens in the background: processing events, making decisions, routing tasks, updating records — all the repetitive, judgement-light work that currently fragments so many people’s days. When those headless agents are running well, nobody notices. The inbox gets processed. The notifications go out. The spreadsheet gets updated. People get their time back. When they’re running poorly — or not at all — somebody _definitely_ notices. Which is exactly why observability isn’t an afterthought for these systems. It’s the whole game. If you’re thinking about where AI agents can make a real difference in your organization, I’d encourage you to look past the chat interface. Look at the event-driven work that’s happening every day. Look at the peripheral tasks that fragment your team’s focus. That’s where headless agents belong. _This post was authored with the assistance of AI._
020
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 24/06/2026
#climate info is available once again. arstechnica.com/science/2026/06/uss…
arstechnica.com
024
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 28/05/2026
I'm talking about #rockbot and #ai #agentic architecture in just over 30 minutes - join me online! www.meetup.com/tulsadevelopers-net/…
011
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 28/05/2026
I created a series of web slides that walk through the philosophy and capabilities of the **#rockbot** agent (built on the RockBot framework). marimerllc.github.io/rockbot-presen… **#ai** **#agent** **#agentic**
001
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 27/05/2026
Watched the last Colbert episode and canceled #paramountplus
000
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 18/05/2026
I’m speaking at VSLive! is sunny San Diego this September. We have labs, deep-dives, and technical sessions exploring the latest in modern .NET, ASP.NET Core, Azure, AI-powered development, GitHub Copilot, Blazor, .NET MAUI, Kubernetes, and modern data platforms. vslive.com/sandiego
001
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 18/05/2026
In just a couple weeks I'm speaking at DevSum in Stockholm on building an #ai MCP server in #dotnet www.devsum.se/agenda/build... #DevSum #SoftwareDevelopment #TechConference
devsum.se
Build an MCP Server in C# - DevSum 2026
Join me as I walk through the process of building an MCP server in C# and .NET, including vector encoding your data, using a hybrid search approach, exposing and testing the MCP endpoint, and more.
053
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 09/05/2026
I use #ClaudeCode across multiple workstations, and finally got around to creating a utility that keeps my claude memories in sync across devices so all the good stuff learned on one PC is always available on another PC. blog.lhotka.net/2026/05/08/C...
blog.lhotka.net
Syncing Claude Memory Across Workstations
VP, Open Source Creator, Author, Speaker
031
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 04/05/2026
My calendar-mcp server now sends and receives email attachments. It is a little awkward, because either (a) the agent uses base64 or (b) the agent uses curl to up/download the attachments outside of the MCP protocol. Sadly, MCP just doesn't have the features to efficiently handle binary content […]
fosstodon.org
Original post on fosstodon.org
001
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 23/04/2026
My #RockBot agent and framework now has its own domain - starting to come together into something people can use! What is it? The RockBot *agent* is an autonomous personal/professional assistant. The *framework* is a rich toolset for building your own agents in #dotnet. rockbot.dev […]
fosstodon.org
Original post on fosstodon.org
011
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 23/04/2026
These days I find myself doing nearly all my work with "pure" Claude Code plus a few skills. I don't use the plugins I used to anymore. blog.lhotka.net/2026/04/23/My-Claud… **#ai** **#agentic** **#softwaredevelopment** **#claudecode**
411
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 23/04/2026
building #ai agents that call tools reminds me of all the browser-specific caveats. It seems like every LLM (even in the same family like #gpt) has its own quirks as to how it formats tool calling output, requiring LLM-specific tweaks. It is the bad old days of the browser, in LLM form!
012
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 23/04/2026
If you’re building agents, understanding the Harness-LLM loop is essential. A lot of what looks like “the AI being confused” is actually the Harness not providing the right context at the right time. blog.lhotka.net/2026/04/22/Agent-Co… #ai #agentic #agent
blog.lhotka.net
Agent Context Needs Timing
VP, Open Source Creator, Author, Speaker
001
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 20/04/2026
#vslive is coming to San Diego, and I'm speaking on #dotnet and #blazor. Beautiful venue, great content, I hope to see you there! bit.ly/48emwy5
Join me (Rocky) in San Diego for VS Live - use discount code LHOTKA
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 17/04/2026
Here are a few presentations from #vslive in March covering #dotnet, #ai, and more. devblogs.microsoft.com/visualstudio…
devblogs.microsoft.com
From AI to .NET: 20 VS Live! Las Vegas Sessions You Can Watch Now - Visual Studio Blog
Watch 20 top sessions from VS Live! Las Vegas 2026, covering AI, .NET, Azure, Visual Studio, and developer productivity, now streaming on YouTube.
001
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 02/04/2026
Today is a big day: the second instance of #rockbot is now running in the wild! So now I know for sure it can run outside my own personal #kubernetes cluster 😀 In this case, my buddy is running it in a #docker compose environment against a local #ollama LLM, which seems to work great
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 02/04/2026
#ai is upending the #softwaredeveloper job, and I believe "systems thinking" is one of the core skills people need to embrace to ride this wave to success. blog.lhotka.net/2026/04/02/Systems-… #claudecode #github #copilot
032
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 26/03/2026
#ai and #agentic systems use skills and tools. I keep hearing people pit these against each other, but really they are complimentary. blog.lhotka.net/2026/03/25/Tools-An…
blog.lhotka.net
Tools and Skills: Better Together
I keep running into a version of the same question when talking about AI agent design: if you have good enough skills — detailed procedural knowledge in markdown files — do you even need MCP servers and other tools? No. You absolutely still need tools. But the question itself reveals a misunderstanding about what skills actually are, and I think it’s worth unpacking. Skills and tools are not competing approaches. You can’t replace one with the other. In practice, they’re deeply intertwined — and trying to pit them against each other misses the entire point of both. I’m going to use RockBot as my example throughout this post because it’s what I’m building and I know it best, but these concepts are not specific to RockBot. Claude Code has its `CLAUDE.md` files and tool use. GitHub Copilot has instruction files, skills, and MCP integration. Cursor, Windsurf, and other AI coding agents all have some form of this pattern. The relationship between tools and skills is a fundamental design concern for any AI agent, not a feature of any one product. ## The Basics I’ve written about RockBot’s tools and RockBot’s skills separately, so I won’t rehash everything here. The short version: Tools are functions the agent can call to take action in the world. Send an email, check a calendar, search the web, invoke an A2A agent, store a memory. Without tools, an agent can only chat. A skill file cannot send an email. A skill file cannot look up what’s on your calendar. Tools are how agents _do things_. Skills are markdown files that capture procedural, context-specific knowledge the agent has built up over time. They encode lessons from past failures, successful patterns, environment-specific conventions, and — critically — knowledge about _how to use tools well_. That last point is the one people miss. Knowing that a hammer exists is different from knowing how to drive a nail without splitting the wood. The hammer is the tool. The technique is the skill. You need both. ## Tools Come with Their Own Skills In RockBot, the relationship between tools and skills isn’t just conceptual — it’s built into the architecture. Every tool subsystem in the RockBot framework can register a base-level **tool guide** when it starts up. This is a default skill that the subsystem itself provides, describing how its tools should be used. When the MCP integration subsystem loads, it registers a guide explaining how `mcp_list_services`, `mcp_get_service_details`, and `mcp_invoke_tool` work together. The A2A subsystem does the same for agent-to-agent communication. The web subsystem explains how search and browsing tools relate. Memory, scheduling, subagents — each subsystem brings its own guide. The agent uses `list_tool_guides` and `get_tool_guide` to discover and retrieve these guides. On day one, before any learning has happened, the agent already has grounded knowledge about how to use its tools — not just what they are, but how to use them effectively. So right from the start, tools and skills are coupled. The tools arrive with skills already attached. ## Skills Improve Through Tool Usage Those base-level tool guides are a starting point, not a ceiling. As the agent uses its tools across real interactions, it learns. It discovers edge cases, finds better sequences, encounters caveats that weren’t obvious from the schema alone. Through RockBot’s feedback loop — explicit thumbs up/down from users and implicit correction signals from conversations — the agent refines and extends its skills. I have a great real-world example of this. A while back, RockBot kept creating calendar events at the wrong time. It would send 4 PM Central to the calendar MCP server, and the event would show up at 11 AM. Four times in a row. It turned out the MCP server had a bug where it silently ignored the timezone parameter and treated all times as UTC. The tool guide for the calendar MCP server didn’t mention this problem — because it didn’t exist when the guide was written. But after that painful debugging session, the agent learned the workaround (send UTC times directly), and that knowledge was captured as an updated skill. The next time the agent scheduled something, it didn’t make the same mistake. That learning was _entirely dependent_ on having the tool in the first place. You can’t learn to work around a calendar bug if you don’t have a calendar. That’s the pattern. The skill describing how to use the calendar MCP server on day one is fairly generic. After weeks of actual calendar management, that skill becomes precise: how to handle recurring events, what to do when attendee time zones differ, what the server does and doesn’t support. The agent has learned by doing, and the skill has grown because of it. ## Skills Do Many Things — Including Making Tools Better I want to be clear that skills aren’t _only_ about tool usage. Skills capture all sorts of procedural knowledge: how to structure a research delegation, what tone to use with different contacts, how to format reports. Many skills have nothing to do with specific tools. But a large and important subset of skills exist specifically to make tool usage more effective. And that’s the insight I think gets lost when people frame this as “tools vs. skills”: skills aren’t an alternative to tools. They’re a _multiplier_ on tools. Skills are operational knowledge — knowledge _about tools_ , _for tools_ , _refined through using tools_. They don’t sit above the tool layer in the architecture. They sit right alongside it, making it work better. ## The Better Together Design What RockBot demonstrates is that these two concepts work in concert at every level: **Tools provide capability.** They are the agent’s connection to the real world — email, calendars, file storage, web, other agents. **Tool guides provide starting knowledge.** Each subsystem ships with a skill that grounds the agent from the moment tools become available. The agent never has to figure out a subsystem entirely from scratch. **Experience improves that knowledge over time.** As the agent uses tools, encounters failures, receives feedback, and discovers edge cases, skills get richer and more precise. Tool usage becomes more effective and more reliable. Remove the tools and you have an agent that can describe how things _should_ work but can’t actually do anything. Remove the skills and you have an agent that stumbles through every interaction, making the same mistakes over and over because nothing it learns ever sticks. Together? You get an agent that keeps getting better at its job. And again — this isn’t a RockBot-specific insight. Whether you’re configuring GitHub Copilot with custom instructions and MCP servers, setting up Claude Code with `CLAUDE.md` files and tool access, or building your own agent framework from scratch, the same principle applies. Tools give your agent the ability to act. Skills give it the knowledge to act _well_. Invest in both.
001
Reposted by Rocky Lhotka 🤘🖖
Lorry @lorry.infosec.exchange.ap.brid.gy · 17/03/2026
This one might be interesting to anyone interested in computer gaming history. I spent the last couple of weeks finally finishing a project I started for Bletchley Park about 20 years ago. Recreating the original MUD (AND the MIST) on a mirror of the original Essex University system that […]
infosec.exchange
Original post on infosec.exchange
022
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 15/03/2026
I have come full circle, from debugging with print statements, through debuggers, and back to debugging with print statements! blog.lhotka.net/2026/03/15/Full-Cir… #softwaredevelopment #ai #dotnet #claudecode #githubcopilot
012
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 12/03/2026
#ai #agentic and #microservices systems both need instrumentation. Combine them like #rockbot, and you _really_ need good metrics to identify issues before they become real problems! blog.lhotka.net/2026/03/11/Tracking…
blog.lhotka.net
Tracking Agent Metrics
Running AI agents in production is not like running traditional software. Token costs accumulate continuously, latency spikes are unpredictable, and the messaging infrastructure that connects agents, subagents, and MCP servers all needs to perform reliably. Without observability, you are flying blind. RockBot and its entire ecosystem — subagents, the research agent, MCP servers, and the internal messaging pipeline — are all instrumented with OpenTelemetry (OTel). This means every LLM request, every token consumed, every message dispatched, and every bit of latency is tracked and exported to the observability stack running in my Kubernetes cluster. In my case, I host all the RockBot related services in my Kubernetes cluster, so this blog post focuses on what I’ve done. However, OTel is supported by all major cloud vendors and environments, and nearly any modern instrumentation or monitoring software works with it. As a result, the RockBot framework’s OTel support means that it plugs into Azure, AWS, or almost any other cloud seamlessly - in a manner similar to what I have set up in Kubernetes. ## The OTel Stack in Kubernetes The Kubernetes cluster runs a standard cloud-native observability stack: * **OpenTelemetry Collector** — receives metrics, traces, and logs from all instrumented services and routes them to the appropriate backends * **Prometheus** — scrapes and stores the time-series metrics data * **Grafana** — provides dashboards and alerting on top of the collected data Every component in the RockBot ecosystem—the primary agent, any spawned subagents, the research agent, and the various MCP servers—emits OTel metrics. This gives a unified, aggregated view across the entire agentic system rather than having to piece together logs from individual services. ## What Gets Instrumented Instrumentation falls into broad categories: LLM economics, agent usage, messaging pipeline health, operational health. For example: ### LLM Economics The economics dashboard captures everything related to the cost and efficiency of LLM calls: * **Cost rate ($/hr)** and **total cost (window)** — how much is being spent on LLM inference right now and over a rolling window * **Avg cost per turn** — the average spend per agent conversation turn, a useful signal for understanding task complexity trends * **Token consumption rate** — input and output tokens per minute, broken down by model * **Token efficiency** — the output/input token ratio over time; a rising ratio can indicate the agent is generating increasingly verbose responses * **LLM calls per turn** — how many LLM invocations happen per agent turn, which helps identify whether subagent or tool orchestration is driving up call counts At a glance, the current average cost per turn is **$0.1461** , with roughly **3.5 LLM calls per turn** on average and a total of **6.21 agent turns** tracked during the window. ### LLM Request Throughput and Latency The usage dashboard digs into the raw mechanics of LLM calls: * **LLM requests/min** — the request rate across all agents and services, showing traffic spikes as agents become active * **LLM request latency (p50/p95)** — response times from the LLM backends, with percentile breakdowns to surface tail latency issues * **Input/output tokens (window)** — rolling token totals by model * **Avg tokens/request** — currently sitting around **22.4K tokens per request** , reflecting the context window sizes in use Latency and throughput together tell you whether the LLM routing layer is performing well. If p95 latency climbs while request rate is low, that’s a signal to investigate the upstream model providers or the routing-stats MCP server. ### Messaging Pipeline RockBot uses an internal messaging pipeline to coordinate between the primary agent, subagents, and the various background services. The messaging section of the usage dashboard tracks: * **Message throughput (published/min)** — how many messages are flowing through the pipeline * **Pipeline dispatch latency** — how long it takes from a message being enqueued to it being dispatched (p50/p95) * **Active in-flight messages** — the current backlog of unprocessed messages * **Messaging publish latency** — the time to write a message to the pipeline * **Messaging process latency** — the time from pickup to completion on the consumer side This is particularly useful for spotting backpressure. If in-flight messages climb while throughput stays flat, something downstream is stalling—whether that’s a subagent blocked on a slow tool call, or an MCP server under load. > ⚠️ I know people tend to favor using the HTTP protocol because it is well-understood and deterministically synchronous. In reality though, a queued messaging system is _far_ more resilient, cheaper, and easier to manage. RockBot supports both models, but I almost always default to queued messaging when given a choice. ## Alerting Having dashboards is only half the value. The real payoff is alerts. Grafana alert rules fire on conditions like: * Cost rate exceeding a threshold (unexpected runaway agent behavior) * LLM request latency p95 spiking (model provider degradation) * Message pipeline backlog growing beyond a threshold (subagent stalls) * Token consumption rate anomalies (prompt injection or unexpected task expansion) Alerts land in whatever notification channel you configure—Slack, PagerDuty, email, or any other Grafana-supported contact point. ## Why This Matters Observability for agentic systems isn’t optional—it’s a prerequisite for running them reliably at any scale. A single misconfigured tool or a prompt that causes an agent to loop can silently burn through token budget before anyone notices. An MCP server with degraded performance can cause cascading latency throughout the entire agent ecosystem. By instrumenting everything with OTel and aggregating it in Grafana, you get: 1. **Cost visibility** — know what you’re spending and catch runaway costs early 2. **Performance baselines** — understand normal latency so anomalies stand out 3. **Pipeline health** — ensure the messaging backbone connecting your agents is functioning correctly 4. **Audit trail** — metrics data supports post-incident analysis when something goes wrong The RockBot ecosystem is designed so that every new agent, every new MCP server, and every new subsystem emits OTel metrics by default. As the system grows—more agents, more MCP integrations, more automation—the observability grows with it automatically. If you’re building production agentic systems, treat OTel instrumentation as a first-class requirement, not an afterthought.
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 10/03/2026
An Agentic Tale blog.lhotka.net/2026/03/10/An-Agent… #ai #agentic #debugging #story
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 10/03/2026
An #ai #agent needs a good set of resources and tools to be useful. This blog post goes through the tools in the #rockbot framework and how they are used by agents. blog.lhotka.net/2026/03/09/Agent-Re…
blog.lhotka.net
Agent Resources and Tools
An AI agent, by itself, can’t actually do anything besides chat. And while it can be fun to have philisophical debates in isolation for a while, eventually we all want to get about the business of actually _doing things_. Agents do things by calling functions or tools. These functions and tools are provided to the agent (the LLM) by the hosting runtime. For example, RockBot is a host that provides a set of tools that can be used by the AI agent. The RockBot _framework_ provides access to a whole set of subsystems, each of which provides tools and guidance to the agent on using the tools. The RockBot _agent_ uses all the features of the framework, plus other capabilities. You can think of these tools as being in logical groups by subsystem. ## Tool Discovery Each subsystem provided by the RockBot framework has the ability to provide its own base-level tool guide to the agent. This way the agent immediately knows how to use things like memory, skills, MCP servers, etc. * list_tool_guides, get_tool_guide When a subsystem is registered during app startup, its tool guide is added to the master list of guides, making it easy for the agent to get the appropriate guide to function. Skills layer on top of these guides, allowing the agent to learn over time. ## Scheduling Tools These are tools that allow the agent to schedule tasks to run at specific times. * schedule_task — Schedule one-time or recurring tasks (cron) * cancel_scheduled_task — Cancel a scheduled task by name * list_scheduled_tasks — List all scheduled tasks ## Subagent Tools These tools allow the primary RockBot agent to spin off subagents to work in the background. Each subagent has access to the same tools and skills, but has its own context memory and a slice of working memory for sharing information with the primary and other subagents. * spawn_subagent — Spawn an isolated subagent for complex/long-running tasks * cancel_subagent — Cancel a running subagent by task ID * list_subagents — List active subagent tasks * report_progress (subagent-only) — Report progress back to the primary agent ## Agent-to-Agent (A2A) Tools Sometimes a subagent isn’t enough, and it is necessary to interact with other autonomous agents in the environment. These tools allow the RockBot agent to interact with other autonomous agents. * invoke_agent — Call an external A2A agent by name and skill * list_known_agents — List all known external agents In a business environment, you can imagine how your agent might interact with other agents that help to manage sales, inventory, production, delivery, finance, and other automation across your organization. ### Agent Examples In the RockBot repo there are two agents to demonstrate how to use the RockBot framework to build agents other than RockBot itself. The first is as simple as you can get. The second is a real external agent that the RockBot agent uses when asked to do any research. 1. Sample agent - Agent that echoes any text sent 2. Research agent - Agent that researches a topic and returns consolidated results ## Memory Tools (long-term) RockBot maintains long-term memory, and these are the tools that support that memory concept. * save_memory, search_memory, delete_memory, list_categories > ℹ️ There are no explicit tools for _conversational memory_ because conversational memory is always part of the agent’s context window. Other memories are brought into context on-demand. ## Working Memory Tools (session scratch space) RockBot also maintains working memory, and these are the tools for interacting with that memory. * save_to_working_memory, get_from_working_memory, delete_from_working_memory, list_working_memory, search_working_memory > ℹ️ As you can see, the RockBot framework and agent have three levels of memory: conversational, working, and long-term. This provides a rich way to manage context window usage, subsystem interactions, and long-term concepts in an elegant manner. ## Skill Tools RockBot has skills, and these are the tools it uses to interact with its own set of skills. * get_skill, list_skills, save_skill, delete_skill Skills develop over time automatically, sometimes refining the base-level subsystem tool guides, other times being created out of whole cloth by the agent as it learns. ## Rules & Configuration Tools These are tools used to manage rules that alter the agent’s behavior. These rules are in addition to the built-in `soul.md` and `directives.md` files that are central to the agent’s identity. * add_rule, remove_rule, list_rules, set_timezone ## Web Tools These are tools that allow the agent to search (using a Brave API key) and retrieve web pages. * web_search — Search the web, returning titles/URLs/snippets * web_browse — Fetch a page and return content as Markdown (with chunking) ## MCP Integration Tools These are tools that allow the agent to find and use MCP servers without having those MCP servers and tools always consuming large amounts of context memory. * mcp_list_services — List connected MCP servers * mcp_get_service_details — Get tool details for an MCP server * mcp_invoke_tool — Execute a tool on an MCP server * mcp_register_server — Register a new MCP server at runtime * mcp_unregister_server — Remove an MCP server at runtime * Plus all tools dynamically registered from configured MCP servers > ℹ️ These tools are a built-in equivalent to the separate mcp-aggregator project. ### MCP Server Examples In my current live environment, here are some of the MCP servers I have registered with the RockBot agent. 1. calendar-mcp - access all my email and calendar accounts 2. onedrive-personal - personal OneDrive 3. onedrive-marimer - work OneDrive 4. todo-mcp - a simple to-do list implementation 5. github - read/write to my GitHub repos 6. routing-stats - get info on RockBot LLM routing 7. openrouter - get info on openrouter.ai usage 8. azure-foundry - get info on Azure Foundry usage ## Script Execution When an agent needs to run some code, it uses these tools to execute scripts. The script executes in an ephemeral container that runs in a separate Kubernetes namespace. * execute_python_script — Run Python in a secure ephemeral container In the future we may support other types of script, such as TypeScript or bash. Python was the obvious start point given its broad use, flexibility, and how well LLMs can generate Python code. ## Conclusion Agents without tools aren’t very useful in any real-world scenarios. The RockBot framework provides a range of subsystems you can use when building an agent, and each subsystem provides a set of tools to the agent. The RockBot agent itself has access to all these subsystems and associated tools. And some subsystems, like A2A, MCP, web, and scripts, open the door for the agent do do virtually _anything_ by collaborating with other agents or invoking external tools, APIs, or code.
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 09/03/2026
Calling all mobile devs! 📱 We're gearing up to launch KidsIdKit, an open-source project for Missing Children Minnesota. We need volunteers w/ expertise in submitting apps to the App Store & Google Play to help us deploy. Want to use your skills for good? Check out the repo and DM me! […]
fosstodon.org
Original post on fosstodon.org
021
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 06/03/2026
#rockbot not only uses skills, but it develops and enhances skills over time so it is able to become more effective and helpful over time without manual intervention! blog.lhotka.net/2026/03/06/RockBot-… #ai #agent #dotnet #agentic
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 04/03/2026
To be useful, #rockbot needs other agents and #mcp servers, because it follows the principle of least privilege. Each has permission to do just what it does. #agentic #ai in action. blog.lhotka.net/2026/03/03/The-Rock…
blog.lhotka.net
The RockBot Band
Over the past several months I’ve been building a set of open source projects that each solve a specific problem in the AI agent space. Individually they’re useful. Together they form the foundation for building truly agentic systems that run in production environments like Kubernetes or Azure. I want to step back and talk about how these projects fit together, because the big picture matters more than any single component. ## The Projects Here’s the lineup: * RockBot — A framework for building agents and multi-agent systems, designed to be cloud-native and manageable. Think of it as the runtime and architecture for agents that communicate through a message bus with full isolation and separation of concerns. * mcp-aggregator — A gateway that sits between your agents (or any LLM client) and all your MCP servers. Agents interact with MCP servers without consuming massive amounts of context memory, and without needing credentials or connection details for each server. * calendar-mcp — An MCP server that provides access to multiple M365, outlook.com, and Gmail email and calendar accounts. Not just one calendar — _all_ of them. Your work calendar, client calendars, personal and family calendars. A real picture of your actual life. * agentregistry — An agent registry for dynamic discovery of A2A and ACP agents, as well as MCP servers. Supports both persistent and ephemeral instances (think KEDA-scaled containers), and agent-to-agent communication via both HTTP and queued messaging. * researchagent — An agent built on the RockBot framework, designed to perform research tasks where results flow back to the calling RockBot agent. Each one addresses a gap I kept running into while building agentic systems. Let me explain how they connect. ## The Agent Runtime: RockBot Everything starts with RockBot. It provides the fundamental architecture: agents as isolated processes communicating through a message bus (RabbitMQ in production). No shared memory, no LLM-generated code running in your host process, no ability for a compromised agent to reach into another agent’s state. I wrote about RockBot’s design in detail in Introducing RockBot, but the key point here is that RockBot is designed from the ground up to run in containers. The framework supports both stateful and stateless agents — state can live in the agent process, in messages, or in external stores, depending on the agent’s needs. Scaling is horizontal for stateless workers, and the registry understands the difference. This matters when you start composing agents together — you need the runtime to support cloud-native deployment, not fight against it. ## A Personal Agent: RockBot Agent The RockBot framework is the foundation, but the RockBot Agent itself is a concrete example of what you can build with it. It’s a personal and professional agent designed to help you manage your life — scheduling, research, information retrieval, task coordination, and more. Unlike the stateless worker agents that spin up, do a job, and disappear, the RockBot agent is stateful by design. It maintains persistent memory about you: your preferences, your projects, your contacts, your communication style. It remembers what you talked about last week and builds on it. This is essential for a personal agent — you don’t want to re-introduce yourself every conversation. The agent uses markdown-based profile files (soul, directives, and style) to define its identity and behavior, and it has a multi-layered memory system with short-term, long-term, and working memory. When it needs to do something beyond its own capabilities — research a topic, check your calendar, interact with external systems — it delegates to other agents and tools through the message bus and mcp-aggregator. The RockBot agent is the hub that ties everything else together from the user’s perspective. ## Tool Access Without the Bloat: mcp-aggregator Agents need tools. MCP (Model Context Protocol) is the emerging standard for giving AI systems access to external capabilities. But if you naively give an agent direct access to a dozen MCP servers, two things happen: your agent’s context window fills up with tool descriptions it may never use, and every agent needs credentials for every server. mcp-aggregator solves both problems. It acts as a single gateway that your agent connects to. The aggregator knows about all available MCP servers, provides concise summaries, and only loads full tool details on demand. Credentials live in the aggregator, not in every agent. I covered this in MCP Aggregator, but the piece I want to emphasize here is how this fits the cloud-native story. In a containerized environment, you configure the aggregator once and every agent in the cluster can use it. Add a new MCP server? Register it with the aggregator and every agent can discover it immediately. No redeployment, no configuration changes across dozens of agent instances. ## A Real View of Your Schedule: calendar-mcp Most calendar integrations give you access to _one_ calendar. That’s fine if you only have one, but most professionals juggle multiple accounts — work (M365), personal (outlook.com or Gmail), maybe a shared family calendar, client calendars, and so on. calendar-mcp is an MCP server that aggregates across all of these. When your agent needs to schedule something or check your availability, it sees the complete picture. Not just your work calendar, but the dentist appointment on your personal calendar and the school event on the family calendar. This is the kind of tool that becomes much more powerful when accessed through the aggregator. The agent doesn’t need to know about OAuth tokens for three different email providers. It asks the aggregator for calendar tools, the aggregator routes to calendar-mcp, and calendar-mcp handles the multi-account complexity. ## Finding Agents and Servers: agentregistry In a static system, you can hardcode which agents exist and where to find them. In a dynamic cloud environment, that falls apart fast. Containers spin up and down. KEDA scales agents to zero when idle and back up when there’s work. New agents get deployed. Old ones get retired. agentregistry provides dynamic discovery for the entire ecosystem. It knows about: * **A2A agents** — agents that communicate via Google’s Agent-to-Agent protocol * **ACP agents** — agents using the Agent Communication Protocol * **MCP servers** — tool servers available in the environment * **Persistent instances** — always-running services, including stateful agents like the RockBot agent that maintain long-term memory * **Ephemeral instances** — stateless containers that scale to zero and spin up on demand (via KEDA or similar) * **Multiple transports** — HTTP for synchronous communication, queued messaging (like RabbitMQ) for asynchronous agent-to-agent work This is the glue that makes a multi-agent system dynamic rather than static. When RockBot needs to delegate a research task, it doesn’t need a hardcoded address. It queries the registry, finds an available research agent, and sends the task — whether that agent is already running or needs to be spun up. ## Specialized Agents: researchagent The researchagent is a concrete example of how this all comes together. Built on the RockBot framework, it’s a specialized agent designed to perform research — web searches, document analysis, information synthesis — and return structured results to the calling agent. In practice, a user asks the RockBot agent something that requires research. RockBot recognizes the need, queries the agentregistry to find a research agent, delegates the task via the message bus, and gets results back. The research agent uses mcp-aggregator to access whatever tools it needs — web search, document stores, APIs — without having its own MCP server configurations. ## How It All Fits Together Here’s the flow in a realistic scenario: 1. A user asks their **RockBot** agent to find a good time to meet with a client next week and prepare background information on the client’s recent projects. 2. RockBot checks availability by invoking calendar tools through **mcp-aggregator** , which routes to **calendar-mcp**. Calendar-mcp checks the user’s work calendar, personal calendar, and the client’s shared calendar. 3. RockBot delegates the background research to a **researchagent** , discovered through the **agentregistry**. The registry knows a research agent is available (or triggers one to spin up via KEDA). 4. The researchagent uses **mcp-aggregator** to access web search tools, the company’s internal knowledge base, and the CRM — all without having direct credentials to any of them. 5. Results flow back through the message bus. RockBot synthesizes the calendar availability and research results, and presents the user with proposed meeting times and a briefing document. No single project does all of this. But together, they provide the complete infrastructure: an agent runtime with proper isolation, centralized tool access, real-world calendar integration, dynamic agent discovery, and specialized agent delegation. ## Why This Matters The AI agent ecosystem is still young, and most frameworks treat deployment as an afterthought. They work great on a developer’s laptop but don’t have answers for multi-tenant environments, dynamic scaling, credential management, or inter-agent coordination in production. That’s the gap I’m trying to close. Not by building one monolithic framework that does everything, but by building focused components that follow established distributed systems principles and compose together naturally. These projects are all open source under the MIT license: * RockBot * mcp-aggregator * calendar-mcp * agentregistry If you’re thinking about building agentic systems that need to run in real production environments, I’d love for you to take a look. Open an issue, ask questions, or contribute. The pieces are in place — now it’s about making them better.
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 03/03/2026
One common challenge with #agentic systems is agent/tool discovery. To solve this, I built a registry service for #a2a, #mcp, #acp, and message-based #a2a, so virtually any agent/tool can list itself for discovery within a system. github.com/marimerllc/agentregistry
010
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 26/02/2026
If feels like #rockbot is finally starting to really come together. Minimal tool calling failures and hallucinations, and hopefully I've got the time zone issues nailed down. It is strange how big things are easy, but the niggling details are always the hardest part! […]
fosstodon.org
Original post on fosstodon.org
000
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 26/02/2026
I love how #claudecode says something will "take a day of focused work" and then plans and implements the entire feature in 30 minutes. Software development has become so much fun again!
022
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 25/02/2026
A discussion of the #ai #agent memory system used by #rockbot to remember conversations, activity, collaboration, and long-term memory. blog.lhotka.net/2026/02/24/A...
blog.lhotka.net
How RockBot Remembers
Many AI models have no persistent memory. Every conversation starts fresh. They don’t remember what you told them yesterday, last week, or five minutes ago in a different chat window. For a casual ass...
231
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 23/02/2026
Lesson learned: use at least #claude haiku if your agent uses tools, cheaper models hallucinate way too much. #rockbot is starting to shape up pretty well today; good tool use, subagents, #a2a agents - truly productive #ai. github.com/marimerllc/r...
011
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 23/02/2026
A tracker for where the DOJ has been and continues to deviate from normal behaviors. www.nacdl.org/Landing/CaseTracker
nacdl.org
NACDL - NACDL Criminal Case Tracker
In response to significant shifts in federal criminal enforcement that depart from historical prosecutorial practices, NACDL has launched a Criminal Case Tracker to monitor and analyze select federal prosecutions that reflect unusual or aggressive uses of criminal law. “Unusual” refers to charging decisions, enforcement theories, or prosecutorial tactics that mark a departure from past norms. The Tracker provides defense counselwith access to key filings, decisions, and outcomes to support effective advocacy.;
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 20/02/2026
Like a human needs to dream, so does an autonomous agent. #rockbot is designed with a dream subsystem so it can organize all sorts of memories, skills, and other information to make its life better and to be more productive when it "wakes up". github.com/MarimerLLC/rockbot
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 20/02/2026
I'm working on #rockbot and am discovering that date/time is almost as hard as dealing with double values and rounding!
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 19/02/2026
I've been working on a #cloudnative #ai agent similar to #openclaw or #nanobot, written in #dotnet to run in #kubernetes. Still a work in progress, but coming along pretty nicely! blog.lhotka.net/2026/02/18/Introduc…
blog.lhotka.net
Introducing RockBot
I’ve been working on a new project called RockBot, a framework for building agent and multi-agent AI systems where agents and user proxies communicate exclusively through a message bus in a cloud-native architecture. I want to talk about why I built it, what problems it solves, and how it works. ## Not Written Here Syndrome OpenClaw kind of took the world by storm when it launched, and is really amazing. I found it very inspirational, but all the (reputed) security issues have made me hesitant to really run it, much less dig in deep. nanobot was inspired by OpenClaw, and seems to be more focused on security and isolation. I actually set up and have been running a nanobot instance for a while, but it has been flaky, at least for me. Lots of hung conversations. With nanobot being under 4000 lines of code, I thought to myself “how hard can it be to build something like this myself?” I have a lot of experience building distributed systems, and I thought I could apply that knowledge to build a more robust and secure agent framework. ## The Problem with Most AI Agent Frameworks Most AI agent frameworks today run LLM-generated code in the same process as the host application. That sounds convenient, but it creates serious problems: * LLM-generated code can access the host directly — file system, network, secrets, everything in the process * Swapping LLM providers or tool backends requires invasive changes throughout the codebase * One runaway agent can crash or compromise the entire system * Scaling individual components is impractical when everything runs together When I started thinking about building autonomous agents, these problems felt fundamental. Not quirks to work around, but architectural failures that need to be solved at the design level. Maybe it is because I’ve built my career around enterprise software, specifically focused on distributed systems. I want something that, while not perfect, at least follows the architectural principles that have proven to work in large-scale, production-grade software. That means separation of concerns, isolation of execution, least privilege, and cloud-native design. ## The Message Bus Architecture RockBot is built around one central idea: agents communicate exclusively through a message bus. There is no shared memory, no direct method calls between agents, and no LLM-generated code running in-process with the host. Each agent is an isolated process that: 1. Subscribes to topics on the message bus 2. Receives messages 3. Invokes tools or calls LLMs as needed 4. Emits responses back onto the bus The message bus is backed by RabbitMQ in production, though that can be swapped out for other implementations if needed. It is easy enough to run a RabbitMQ instance in Docker Desktop for local development. This isn’t a new idea. Event-driven architecture has been around for decades. What’s new is applying it rigorously to AI agent systems, where the isolation properties matter even more than in traditional software. ## Four Design Goals RockBot is built around four foundational goals: **Separation of concerns.** Every responsibility has a clear owner with a well-defined boundary. Agents handle reasoning. The message bus handles routing. Tool bridges handle execution. LLM providers handle inference. None of these cross into each other’s domain — they communicate only through typed messages. This makes each layer independently testable, replaceable, and understandable. **Isolation of execution.** LLM-generated code never runs in the same process as the host. Agents run in separate processes with no shared memory. Scripts execute in ephemeral Kubernetes containers that are discarded after use. A compromised or runaway agent cannot access the host, read its secrets, or affect other agents. Failure is contained by design. **Principle of least privilege.** Each component knows only what it needs to do its job. Agents receive only the messages addressed to them. Tool bridges expose only the tools they are explicitly configured to serve. Scripts run in containers with no network access, no persistent storage, and no credentials. No component accumulates capabilities beyond its immediate task. **Cloud-native by design.** Outside the core agent itself, workers are stateless — state lives in messages or external stores, never in process memory. Components scale independently. The message bus provides back-pressure, dead-letter queues, and durability so the system degrades gracefully under load. Configuration flows from the environment, secrets from Kubernetes Secrets, and observability out through OpenTelemetry. ## Core Components The framework is composed of several focused packages. Here are some key ones: Package | Purpose ---|--- RockBot.Messaging.Abstractions | Transport-agnostic contracts (IMessagePublisher, IMessageSubscriber, MessageEnvelope) RockBot.Messaging.RabbitMQ | RabbitMQ provider with topic exchanges and dead-letter queues RockBot.Messaging.InProcess | In-memory bus for local development and testing RockBot.Host | Agent host runtime — receives messages and dispatches through the handler pipeline RockBot.Llm | LLM integration via Microsoft.Extensions.AI RockBot.Tools / RockBot.Tools.Mcp | Tool invocation — REST and MCP (Model Context Protocol) RockBot.Scripts.Container | Ephemeral script execution in isolated Kubernetes containers RockBot.A2A | Agent-to-agent task delegation over the message bus RockBot.Cli | Unified host application — runs agents as hosted services The abstractions layer is deliberately thin. If you want to swap RabbitMQ for a different message broker, you implement a new provider against the same contracts and nothing else changes. ## Agent Profiles One thing I particularly like about this design is how agents are configured. Each agent gets three markdown files: * `soul.md` — Core identity, values, and goals * `directives.md` — Behavioral rules and constraints * `style.md` — Tone, formatting, and communication style These files are human-readable, version-controlled, and composed at runtime into the agent’s system prompt. This means you can adjust an agent’s behavior without touching code, just by editing its profile files. It also means your agent configuration is right there in source control alongside your code, reviewable and auditable by the whole team. ## Bridges to the World RockBot supports Model Context Protocol (MCP) for tool integration. Place an `mcp.json` file alongside `RockBot.Cli` and the MCP bridge will discover and register available tools automatically. This means any MCP-compatible tool server can be plugged in without writing glue code. This is particularly useful because the MCP ecosystem is growing rapidly. If a tool has an MCP server, RockBot can use it. The MCP bridge shields the agent from having to know details about all the MCP servers that may be registered. It maintains and provides a list of available MCP servers, and only provides tool details on-demand. This avoids overloading the agent’s context window with information about tools it may never use, while still making them available when needed. RockBot also supports web searching and browsing, which allows the agent to search and read web content. Typically this content gets pulled back into searchable working memory so the agent can reason over it without needing to access the web repeatedly. And there is support for executing arbitrary Python scripts in isolated containers. This allows agents to perform complex computations, data processing, or interactions with external systems without risking the host’s security. ## Memory and State The agent itself does have persistent memory at several levels: 1. Short-term working memory is passed in the system prompt and updated with each message. This is where the agent’s current context lives. 2. Long-term memory is stored as a set of files in a folder structure defined by the agent. These files include tags, and support lexical retrieval to pull relevant information into the agent as needed. 3. Working memory is in-memory and ephemeral. This is where the agent can stash blobs of information from the web, MCP servers, or after running scripts. Think of this as a short-term cache that the agent can use to hold information it is actively reasoning over, without needing to write it to disk or include it in the system prompt. ## Skills The agent can maintain its own set of skills: markdown files with instructions on how to do whatever the agent needs to do. I’m finding that it is often very beneficial to have a skill for each MCP server or each workflow the agent needs to perform. This allows the agent to learn how to use tools over time, and to have a clear place to look up instructions on how to do things. ## User Interaction There are two user proxies at the moment: a CLI tool for testing, and a Blazor web UI for actual use. The user proxy concept is extensible, so it is quite possible to create all sorts of other user interfaces. A user proxy communicates with the agent via RabbitMQ messages, just like any other agent or component. This means the user interface is completely decoupled from the agent’s reasoning and tool execution. The UI can be swapped out, scaled independently, and even run on a different machine or in a different environment without affecting the core agent logic. ## What’s Next The project is still early. The core architecture is in place, the RabbitMQ and in-process transports work, LLM integration is done via Microsoft.Extensions.AI, and the Blazor Server UI is functional. There’s plenty more to build, and the design is intentionally extensible. If you’re interested in multi-agent AI systems and care about security, isolation, and cloud-native deployment, I’d love for you to take a look. The repository is at https://github.com/MarimerLLC/rockbot. Contributions are welcome — just open an issue before starting significant work so we can discuss the approach. The AI agent space is moving fast. My goal with RockBot is to build something that makes it possible to create serious, production-grade agentic systems without sacrificing the security and architectural principles that make software sustainable over time.
030
Reposted by Rocky Lhotka 🤘🖖
Rocky Lhotka @rocky.lhotka.net · 17/02/2026
I didn't listen to the podcast, but this guy is totally channeling the ideas Alastair Reynolds used in his 'Revelation Space' novels about gamma, beta, and alpha versions of people as an AI. Another example of why reading #scifi is so critical! These ideas aren't new! hbr.org/podcast/2026...
hbr.org
With Rise of Agents, We Are Entering the World of Identic AI
A conversation with tech expert Don Tapscott about the potential for and pitfalls of identic AI.
011
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 16/02/2026
Suffering from #mcp server overload? Need better management, security, use of #llm context windows? Your #ai struggling to use your #mcp server well? I know I have been facing this, so I built #mcp-aggregator to try and fix it. blog.lhotka.net/2026/02/15/MCP-Aggr…
blog.lhotka.net
MCP Aggregator
If you’ve been using AI coding tools like Claude Code, Cursor, or GitHub Copilot, you’ve probably started connecting them to MCP servers. One server for your database, another for your docs, maybe one for your company’s internal APIs. It works great — until you have five or six servers configured, each tool needs its own copy of the configuration, and every server connection is sitting open whether you’re using it or not. That’s the problem I set out to solve with mcp-aggregator. ## The Problem with Many MCP Servers The Model Context Protocol is fantastic for giving AI tools access to external capabilities. But the current model has each AI tool maintaining its own direct connection to every MCP server you want to use. This creates a few headaches: 1. **Configuration sprawl** — Every tool (Claude Code, Cursor, VS Code, etc.) needs its own copy of every server’s connection details. Add a new server? Update the config in every tool. Change a server’s address? Update everywhere again. 2. **Multi-PC management** - In my case, I typically work across three different PCs, depending on where I am and what I’m doing. Manually keeping Claude Desktop and Claude Code and Copilot MCP configurations in sync across all these devices is _really painful_! 3. **Resource waste** — All those connections sit open even when the AI isn’t using them. Most of the time your AI tool is calling one or two servers, but all of them are consuming resources - or at least consuming valuable context memory in your LLM. 4. **No central management** — There’s no single place to see what servers are available, add new ones, or remove old ones without touching every tool’s configuration. 5. **Security** - Everywhere you register an MCP server (in Claude Code, Claude Desktop, Copilot, and across computers) requires that you replicate any API keys or other secrets necessary to talk to the MCP server. This is a security nightmare - just like putting your database credentials on every client PC instead of on an app server. 6. **REST vs MCP** - Some LLM tools and communities are not fans of MCP, and prefer REST API endpoints. This aggregator supports both types of endpoint, so if your LLM client supports MCP that’s great. If it doesn’t, almost _everything_ can call a REST API endpoint, so there’s a great fallback. ## One Connection to Rule Them All The mcp-aggregator acts as a gateway between your AI tools and all your MCP servers. Instead of each tool connecting to every server directly, each tool connects to the aggregator. The aggregator manages all the downstream server connections. Your AI tool configuration goes from this: { "mcpServers": { "database": { "command": "..." }, "docs": { "command": "..." }, "internal-api": { "command": "..." }, "jira": { "command": "..." } } } To this: { "mcpServers": { "aggregator": { "url": "http://localhost:8080/mcp" } } } One connection. All your servers are still available, but the aggregator handles the routing. ## My Scenario I typically move between three (or more) different client devices. On each device I run three or more LLM client tools. This is a lot of MCP json config files to maintain manually! And a lot of security keys to juggle. And I started using nanobot, an agent inspired by OpenClaw. One core philosophy behind nanobot is isolation - keeping the agent separate from tools it might use. MCP Aggregator follows that philosophy as well, with the idea that nanobot (or other LLM clients) can talk to the aggregator, and the aggregator manages what remote MCP servers are available, including their credentials, etc. So your LLM client (including nanobot) don’t have those security keys or URLs or anything. From my understanding, the OpenClaw world is less excited about MCP support, which is why MCP Aggregator also supports a REST API that mirrors the MCP capabilities. So if you don’t like MCP and prefer simple API calls you are all set. Now, instead of managing my MCP server registrations 12 or more times across different devices and apps, I manage them in one location. So much simpler! ## Lazy Loading and Idle Timeout One of the design decisions I’m most pleased with is lazy loading. The aggregator doesn’t connect to a downstream server until someone actually calls one of its tools. If you have ten servers registered but only use two during a session, only two connections get opened. And connections don’t stay open forever. After a configurable idle timeout (30 minutes by default), unused connections are automatically closed. They’ll reconnect seamlessly the next time a tool is invoked. This means the aggregator is efficient by default, without any manual connection management. ## Dynamic Registration You can add and remove MCP servers at runtime without restarting anything. The aggregator exposes both MCP tools and a REST API for server management, so you can register a new server with a simple API call or even have your AI tool do it for you. This is particularly useful in environments where servers come and go, or when you’re experimenting with new MCP servers and don’t want to restart your AI tools every time. Also, when you use multiple client devices, because you only need one MCP configuration per device per LLM client. Because some MCP servers expose _lengthy_ documentation in their descriptions, mcp-aggregator supports the use of an LLM to read and summarize MCP server descriptions as they are registered, ensuring that the top-level descriptions provided by mcp-aggregator to your LLM client are short and concise. The client LLM can then get all the details on-demand, but we protect that precious LLM context memory even if you have a lot of MCP servers, or some MCP servers with lengthy description text. ## Skill Documents One feature that emerged from real usage is skill documents. These are markdown files that describe _when and how_ to use a particular server’s tools. Think of them as instructions that help the AI make better decisions about which server to call for a given task. When an AI tool asks the aggregator what’s available, it gets back concise summaries. When it needs more detail, it can drill down into a specific server’s full tool schemas or read its skill document. This two-step discovery process keeps the initial response small while still providing rich information when needed. These skill documents can be provided by an MCP server author, or you can have your LLM explore an MPC server once and store its own skill document with mcp-aggregator so future uses (by all your LLM clients) will have access to that valuable document. ## Built with .NET The aggregator is built with .NET 10 and is available as both a stdio server (for direct integration with tools like Claude Code) and an HTTP server (for shared/networked deployments). There are also Kubernetes manifests if you want to run it in a cluster. The project is open source under the MIT license at github.com/MarimerLLC/mcp-aggregator. If you’re juggling multiple MCP servers across multiple AI tools, give it a try. ## Hosting Because the aggregator is built with modern .NET 10, it can run on Linux, Mac, and Windows. You can host it locally via stdio (for simple one-PC scenarios), or on your private network. I like hosting in my personal Kubernetes cluster so it is available to my other pods and all my PCs and devices on my network. ## Future This is a first release, and I’m sure it will improve over time. Some ideas I have already include multi-user support (right now this is designed for use by a single user), authentication keys so the server could be hosted on the public Internet, and I fully expect to discover more features that would be beneficial as I (and others) use this tool.
111
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 16/02/2026
The calendar-mcp project has moved, and now also has an http endpoint (not just stdio). And better authentication for your email providers. Basically, all around better than a couple days ago! Want #calendar and #email in your #AI? Check it out! github.com/marimerllc/calendar-mcp
010
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 12/02/2026
Writing for an #ai isn't the same as writing for humans. blog.lhotka.net/2026/01/11/Writing-…
blog.lhotka.net
Writing Docs for an AI
I’ve been writing a lot of documentation for CSLA recently. Not for humans, but for AIs. When I tell people I’m writing for an AI and not a human, they often ask “what’s the difference?” It’s a good question. After all, both AIs and humans read text. But there are some key differences in how they process information. When writing for a human, you need to make certain assumptions about their background knowledge, and it is always better to assume less than more. I know I find it frustrating when I come to a document and the author has just assumed I’m already a Linux IT expert or that I know all about some niche tool. Writing for a human means explaining every bit of jargon, expanding any acronyms, and providing context for any concepts that might not be universally known. You also need to consider the flow of the document, making sure it is engaging and easy to follow. The flow or structure of a human-focused document is often more important than the content itself. You want to keep the reader engaged and interested in what you have to say. This means using storytelling techniques, such as anecdotes or examples, to illustrate your points and make them more relatable. When writing for an AI, you can assume that it has access to a vast amount of information and can understand complex concepts without needing them to be explained in detail. An AI either knows, or can instantly look up, any term, acronym, or concept you mention. This means you can be more concise and to the point when writing for an AI. In fact, you _want_ to be concise, as the longer your document, the more of the LLM context window you will consume, and the more likely it is that the AI will forget important details from the beginning of the document by the time it gets to the end. When writing for an AI, you also need to consider how it processes information. AIs are designed to analyze and understand text in a very different way than humans. They can quickly identify patterns and relationships between different pieces of information, and they can use that information to generate new insights or make predictions. The flow or structure of a document for an AI is less important than the content itself. AIs are not easily distracted by tangents or irrelevant information, so you can focus on providing the necessary information in a clear and concise manner. There are commonalities. Either way, you want to be clear and concise. Avoid unnecessary words or phrases that don’t add value to the document. Use simple language and avoid jargon whenever possible. And always proofread your work to ensure it is free of errors and easy to understand. This is true for human and AI consumers. I think about the books I’ve written over the years, and just how much content was in each chapter to help guide the reader through the material. To explain concepts, jargon, acronyms, etc. More experienced readers, I’m sure, just skimmed over those sections, but they were indispensible for less experienced readers. When I write documentation for an AI, I can skip all of that. I can just get to the point and provide the necessary information without worrying about whether the reader will understand it or not. The AI will either understand it or it won’t, but it won’t be confused by extraneous information.
001
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 10/02/2026
Strongly typed I'd values in #dotnet is a good idea. blog.elmah.io/pimplementing-strongl…
blog.elmah.io
Implementing strongly-typed IDs in .NET for safer domain models
Stop using primitive types for IDs. Learn how to implement strongly-typed IDs in .NET and EF Core to catch logic errors at compile time.
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 05/02/2026
@jasonbock talks about cool code gen stuff in #dotnet www.dotnetrocks.com/details/1988
dotnetrocks.com
.NET Rocks! is a weekly talk show for anyone interested in programming on the Microsoft .NET platform. The shows range from introductory information to hardcore geekiness.
000
Rocky Lhotka 🤘🖖 @rockylhotka.fosstodon.org.ap.brid.gy · 29/01/2026
I’ll be speaking at VSLive! Las Vegas this March, and it’s one of the best ways I know to start the year. The timing matters. This is training you can apply immediately to 2026 projects, not ideas that sit on a backlog for months. If you’re planning to attend […] [Original post on fosstodon.org]
001