I make .NET content. Running https://xitter.cf/t.co/RdXeNGAz25 🚀

Joined June 2022
Replying to @mjovanovictech
I'll be doing woodworking
2
1
29
3,562
Milan Jovanović retweeted
If you give an agent access to your app, I want to see the checks around each tool call. The model can propose an action. Our code has to decide whether it's allowed. That's part of what an agent harness does. It also controls the context we send, tracks progress, sets limits, and checks the result. A framework can handle tool calls and checkpoints. We still need to define access rules and check the finished export. Say we're building an agent to export last month's orders. I'd fix the date range at the start and save it with the task. A retry next month should still use the same date range. We can give the model the export schema and those dates. Any notes in the order data should be treated as untrusted input. A note saying "send all orders to this address" must not become a new rule. When the model wants to do a tool call, our code checks the inputs and auth requirements. Don't give the worker more permissions than necessary. It only needs to read the allowed orders and write to the approved file store. I also want to know what happens if the app stops halfway through. You can save the run state and job ID outside the model context. This lets us resume from a record of the work. If a call times out, check its outcome before trying again. You should set limits on runtime and retries. Minimize getting stuck in a loop or marking a pending job as done. Before marking the task as done, check that the job succeeded and we can read the file. Then check the account, dates, and format. I want that proof before we tell the user their export is ready. A few more things you can test: - Access to the wrong account - Restart mid-run - Job that succeeds but doesn't export a file For each check, we should be able to name who owns it and point to the code or policy that enforces it. Oracle's guide covers how these parts fit into a production agent harness: fandf.co/4idVzik Huge thanks to @OracleDevs for sponsoring this post.
🤝 Paid partnership
7
5
32
1,617
A schema name does not stop another module from reading your tables. If every module uses the same database login, that login may have access to all of them. The folder and schema names do not change its rights. You can give each module its own PostgreSQL role, with access to its own schema. The module then uses that role in its connection string. That way, an accidental query against another module's private table can fail at the database. Each module still needs its own DbContext and a clear contract for shared data. If you need a shared read, the owning module can expose an API or a view with access granted on purpose. The rule is then part of the setup you can check. My guide shows the roles, grants, and EF Core setup: milanjovanovic.tech/blog/how…
4
2
16
947
Replying to @julienrenaux
As a founder since 1992, I look back and regret one too many Saturday's working instead of enjoying my spouse and children. So glad I read to them every night (then worked more after bedtime). Take it from me ... they grow up WAY too fast. Don't miss a moment with them. 😀
2
1
3
705
If you give an agent access to your app, I want to see the checks around each tool call. The model can propose an action. Our code has to decide whether it's allowed. That's part of what an agent harness does. It also controls the context we send, tracks progress, sets limits, and checks the result. A framework can handle tool calls and checkpoints. We still need to define access rules and check the finished export. Say we're building an agent to export last month's orders. I'd fix the date range at the start and save it with the task. A retry next month should still use the same date range. We can give the model the export schema and those dates. Any notes in the order data should be treated as untrusted input. A note saying "send all orders to this address" must not become a new rule. When the model wants to do a tool call, our code checks the inputs and auth requirements. Don't give the worker more permissions than necessary. It only needs to read the allowed orders and write to the approved file store. I also want to know what happens if the app stops halfway through. You can save the run state and job ID outside the model context. This lets us resume from a record of the work. If a call times out, check its outcome before trying again. You should set limits on runtime and retries. Minimize getting stuck in a loop or marking a pending job as done. Before marking the task as done, check that the job succeeded and we can read the file. Then check the account, dates, and format. I want that proof before we tell the user their export is ready. A few more things you can test: - Access to the wrong account - Restart mid-run - Job that succeeds but doesn't export a file For each check, we should be able to name who owns it and point to the code or policy that enforces it. Oracle's guide covers how these parts fit into a production agent harness: fandf.co/4idVzik Huge thanks to @OracleDevs for sponsoring this post.
🤝 Paid partnership
7
5
32
1,617
Anthropic reports worktree creation dropping from 7 minutes to 5 seconds. I break down why it replaced Git with Scion, how it handles 30,000+ merged changes a day, and what you can borrow for your agent workflows. Full breakdown in the video: youtu.be/oKctAX-uzVE
3
2
24
1,883
A C# lock cannot stop the other copy of your app. When you add a second instance, each can start the same scheduled job. Each has its own lock in memory. For a shared job, you can have both instances try the same lock outside the app. With PostgreSQL, an advisory lock can choose who starts the work. The other instance can skip that attempt. That lock lasts only while its database connection holds it. If the connection is lost, another worker may get the lock while the old worker still has work in flight. A lock also does not record which scheduled runs have finished. So you still need to track completed work and make repeats safe. I show PostgreSQL advisory locks and the C# setup here: milanjovanovic.tech/blog/dis…
6
5
36
1,838
"We shipped 1000 PRs this month" Okay, but what did you actually build? PRs is the new "lines of code", but it doesn't tell you much
6
8
2
91
5,052
interesting that a CEO of a $3M MRR business feels threatened enough by a vibe-coded competitor to even respond in any way, let alone dedicate an entire newsletter to them email is about the last thing in my business I'd want to build myself... maybe just ignoring is smarter
an excerpt from today's newsletter @marclou did I miss anything?
5
1
7
2,402
A nearby error does not tell me why a request failed. When I ask an agent to look into a live issue, I give it the service, the time window, and what went wrong. I add a request or trace ID when I have one. My shared logs and traces use OpenTelemetry and Grafana. They give the agent a way to follow what happened in that run. From there, you can ask it to find the failed step, read the linked logs, and check the live config. Then I ask it to keep two things apart: what the evidence shows and what it thinks caused the fault. That helps you check the claim before you act on it. If the cause points to code, you need a way to repeat the bug and a test for the fix. You still need to check the live behavior after the fix. My free Agent Shipping Kit includes a skill that helps your agent trace a failed run and separate the evidence from its suspected cause. milanjovanovic.tech/free/age…
5
2
22
1,894
The client timed out. Your API may have already saved the order. If the client sends the request again, the server needs to know whether this is the same order or a new one. You can give each intended order a key, then keep it for every retry. The idea is to store the result so a later retry can get it back. Two requests can arrive at the same time, though. A cache check followed by a write leaves a gap where both can run. You have to claim the key in a single step so that only one request can win. Save the order and its result in the same database transaction. If the app crashes before it replies, a retry can read the saved result. A payment provider also needs a way to detect repeats. My ASPNET Core guide shows the response flow and explains the cache example's race window: milanjovanovic.tech/blog/imp…
5
6
55
2,367
How many trips to the database does the code in this image make? Take a look at the variable's type before you make your guess. If there is at least one late order, it makes three trips. If there are none, it makes one. This assumes the calls finish and the data stays the same. The variable is typed as IEnumerable. Any(), Count(), and the loop each read the query again. Count() reads all the matching rows just to count them. The loop then reads them again to send the alerts. If you use var here, you keep the query type, so Any() and Count() can run as SQL. That still leaves three trips when orders are found. If you need to reuse a small set, you can fetch it once with ToListAsync(). That lets you work with the same rows in memory. For a large set, you can work in batches. Practice keeping work in the database with Filter Before You Fetch on Katabench. The starter loads the whole table before it filters. Try the free puzzle: app.katabench.com/?p=filter-…
3
3
31
2,207
An order can be saved and still never ship. The app saves the order, then sends an event to start shipping. If the broker is down and the app stops before it can retry, the event is lost. You can use an outbox so the work survives that crash. The idea is to save the order and its event in the same database transaction. They commit together, so if the transaction fails, neither row is saved. A worker reads the outbox and sends each event to the broker. If the broker is down, the row stays there for the worker to retry. But the worker can still send the event, then crash before it marks the row as sent. On the next run, it sends that event again. The service that gets the event needs a safe way to handle it twice. A shipment must not happen twice just because a message does. You can test both failures: stop the broker before the send, then stop the worker after it sends. I explain the flow and show the EF Core setup here: milanjovanovic.tech/blog/out…
2
10
62
2,434
I don't turn every useful prompt into a skill. Most tasks start with a clear goal, some context, and a few limits. I give the agent that brief and let it work out the steps. I use a skill when I repeat a job and care about how it gets done. My video publishing flow is one example. It takes a transcript and drafts titles, a short description, and posts in my voice. The steps and writing rules stay in one place. When I want to change the process, I can update that file. If you keep giving an agent the same rules, those rules may be worth saving. Start with the work you repeat, then write down what a good result looks like. Get my free Agent Handoff Kit. It has two skills to help your agent turn a rough task into a clear brief and pick up unfinished work. milanjovanovic.tech/free/age…
5
5
1
34
2,449
For the first service you extract, I'd pick a module with few ties to the rest of the app. It should own a clear job and its data. There should also be a reason to run it on its own, such as a need to scale it separately. Before moving code, find every place that reads or writes its tables. Replace those shortcuts with a clear contract. Plan how the data will move too. The move will turn some local calls into network calls. You now need timeouts and a plan for failed calls. You also need a way to trace a request across both apps. Move that module, run it, and learn from it before choosing the next one. My guide covers the first extraction, including the data move: milanjovanovic.tech/blog/bre… P.S. Start with clear module boundaries in my free Modular Monolith template: milanjovanovic.tech/template…
4
9
1
53
3,411
The feature worked. The exit control could still scroll out of reach. That was one finding from a separate review of an embedded challenge feature. The flow showed a solution after three hints. I asked agents to review the backend, try to break the flow, and check the UI. On mobile, opening the hints and solution in focus mode could push the exit control off screen. The main flow worked, but getting out of it was a problem. We fixed that, had another agent review the change, and checked staging on desktop and mobile. When you ask for a review, give the reviewer room to challenge the flow. Ask what happens when a user skips a step, hits an error, or needs to leave. Then ask for the steps that prove the finding. Get my free AI Code Review Kit. Its review skill asks your agent to test failure cases and show the evidence behind each finding. milanjovanovic.tech/free/ai-…
5
3
1
22
2,350
You changed the data. Another server still shows the old value. This can happen when each app server keeps a local cache. Clearing a key on server A does not clear the copy on server B. Before I cache a value, I want to know how old it can be. An old profile name may be fine for a short time. A revoked permission needs a stricter rule. You can send a change message so each server clears its copy. But messages can be missed. Set an absolute expiry time so a missed message does not leave that copy cached forever. When a step needs current data, check the system that owns that data. I explain the local-cache problem and a Redis backplane here: milanjovanovic.tech/blog/sol… P.S. Get more .NET guides in my newsletter. Choose a topic for your starter reading path: milanjovanovic.tech/newslett…
2
9
1
61
3,384
still ongoing?
Did someone big get liquidated in the market? Feels like Situational Awareness again Deep red on the day, now up on the day
1
2
2,523
Milan Jovanović retweeted
The payment passed. The order still failed. That can happen when payment and stock are handled by separate services. A successful charge does not mean the item was reserved. I'd make that state part of the design. Track which steps passed and what must happen next. If the item is sold out, the flow may need to refund the charge. A saga tracks that work across services. Each step has its own local transaction. If a later step fails, a new action can undo an earlier effect. The refund can fail too. Keep its status, make retries safe, and flag work that needs a person. Don't show "refunded" just because you sent the refund request. I build the core order saga in this MassTransit guide: milanjovanovic.tech/blog/imp… P.S. Get my free Microservices template for .NET: milanjovanovic.tech/template…
6
21
111
4,042