All articles

Table of contents Introduction Cost considerations Code review comments Improvements mid-way Our pain points Performance considerations Main takeaways Resources Conclusion This blog post is part of a series where I share how AI is augmenting my work, and what I'm learning from it. If you're interested, you can read the second post here: Lessons learned improving code reviews with AI. Our approach was simple: experiment in order to learn what works. We are still learning and improving, but the more we use and optimize these tools, the more leverage we gain as a team. Let's get into the details. Okay... we all have heard of Copilot coding agent by now. You probably have heard that at GitHub, this agent is the number 1 contributor in their code base at the keynote and their roadmap webinar Q1 2026 Well... to me this is the same statement that Dario, CEO of Anthropic, made of "in 3-6 months AI is writing 90% of the code". I'm glad it works for them, and they can spend their marketing budget and strategy on these slides and statements. But it's not the metric I care about. I'm fine not having to type in a keyboard to write 90% of the code, but measuring LOC just doesn't make sense to me. That says nothing about the quality of the merged code, bugs introduced, etc. They are hype-driven statements in my opinion 🀣. We have been doing quite a bit of experimenting with GitHub Copilot coding agent and Claude Code, to try to answer this question. Maybe we can replace most of our typing on a keyboard to prompting. Our goal is nothing like GitHub, we have nothing to sell... they do πŸ˜…. Our motivation is to keep improving the way we work and bring value to real customers. So I'll share what we have done and experimented with GitHub Copilot coding agent πŸ™‚. We planned this before the change to usage-based billing, since I had still 70% premium tokens left in August, and they reset every month, we were like: Why not spend them all in a ton of coding agent experiments πŸ˜„ ! So we did πŸ˜†. Our approach was this: Pick 1 task that is prioritized for our next release to give to the coding agent Pick 1 other backlog item or general task we would like to be done, some bugfixes, or code improvements Assign all tasks to a coding agent (most would be Copilot, others would go to Claude third-party agent) Go do another task, then after a while, review PRs Report on the premium token usage + number of PRs + quality of the output + number of comments Start the cycle again with more tasks on the next month Again, our goal is to experiment in order to learn what works. We did this experiment in August 2025, some other months and again in March 2026 (mainly since there were many improvements introduced). It's important to note our focus was on Copilot, not any other third-party agent. We did not use Codex, and only used Claude on some of the tasks for this experiment. We did not analyze or think a lot about costs. The goal was to experiment and see the quality of the PRs on different tasks. But suffice to say, the billing change is a necessary change. We were able to hit the 59min timeout on tasks that should not cost 1 premium request, or get a lot of tool calls for that cost, like: Prompt Branch changes against master Output please check all work that is done here in this branch, vs the master branch, and do a thorough code review using all skills available. Focus on bugs and then code quality too. Use multiple subagents, each with their own perspective and goal ~47,300 additions and ~11,000 deletions Error hitting 59min timeout. Used 4 subagents. We hit the error model_max_prompt_tokens_exceeded with the message "prompt token count of 530706 exceeds the limit of 64000" improve memory consumption of function X. Acceptance criteria: Memory should not exceed Y, regardless of the amount of items being processed. ~900 additions and ~40 deletions Success in 53min I'm sure you have seen plenty of engineers using a lot of inference for 1 premium request or for 20 dollars of a Claude Code subscription πŸ˜…. Anyway, if we were to adopt Copilot Coding agent in June, we would need more controls to control GitHub actions minutes and overall token usage + re-evaluate the cost-benefit. I'll share an approximation of the results we got: Author PRs Merged Merge rate Copilot coding agent ~130 ~30 ~23% Third-party Claude agent ~5 0 0% Human developers ~400 ~390 ~98% Size (lines changed) Copilot/Claude PRs S (10-49) ~12 M (50-199) ~48 L (200-999) ~55 XL (1000+) ~20 Again, this is mainly an experiment so merge rate is expected to be very low. A lot of Copilot coding agent PRs were spikes/exploration or using GitHub custom agents to analyze PRDs, do security reviews, etc. Let's talk about the quality of the PR when Copilot asked me for a review. First and foremost, I don't think we have a high bar for quality PRs compared to other successful software teams. To me, a high-quality PR is expected, always, period. Second of all, many draft PRs I've created and seen other engineers create, is usually a v0. It's a version we publish to get feedback from engineers on our team, it's never actually ready to be merged. All Copilot PRs are created as drafts, to me this signals Copilot really just did a v0, even if it says it has completed everything and everything works. My current opinion is this is made on purpose, to give you a chance to steer Copilot again in its implementation, and do an initial code review to spot things that are wrong. I've not seen any docs, or official statements from GitHub supporting my claim. With that said, I'd like an option to enable Copilot to continue iterating on their PR and only ask me for a review when it's no longer a draft. But this coding agent might not evolve in that direction since their marketing and docs so far are focused on small & medium tasks. Cost control becomes very important too with long-running agents. To simplify things, we'll say asking me for a review is the same as another engineer asking me to review their PR. Any engineer in our team (or generally in the world) only assigns a co-worker a PR for review once the PR is ready, has finished work and they tested and reviewed their own work. From our experiment so far, Copilot was not able to have a ready and polished PR in most PRs, so I need to leave a lot of comments saying the countless wrong parts. One of the problems is the feedback loop, we didn't make the Playwright MCP work for us since we have limitations on the front-end login flow. So the agent doesn't deliver the necessary code for front-end tasks. In terms of the comments I made, alongside CCR and Claude Code before marking the PR as ready for review, it's around 20-30. The ones that got merged usually had under 20 comments and most discussions weren't critical or about low-quality code. Again, it appears to me these were mostly low-medium tasks that were clearly defined and the agent did well. Our closed PRs and a few of the experiments got 40+ comments, for various reasons: Unnecessary test cases Re-implemention of certain modules and functions was necessary Removed existing functionality Low quality code and not adhering to coding standards and best practices (e.g. a lot of duplicated code, missing error handling) Missing front-end implementation Usage of non-existent CSS classes The ones that got closed and were simple experiments didn't receive much review. I understand that isn't a great thing for the experiment, but we simply invested more time in some PRs rather than all, again some are just spikes or over the top on purpose. It's not the same thing as our own team PRs, of course, since these draft PRs are done in like ~15min. But the number of comments necessary to have these draft PRs ready to be reviewed by another human (and AI tools, like Copilot itself, Claude and CodeRabbit) is important. Since it's time I'm spending reviewing code. I don't want to be bothered when there are still typos and acceptance criteria is not fully met πŸ˜…. I had features Copilot coding agent didn't do very well, which then prompted me to ask for a way to ask clarifying questions. The agent dashboard is nowadays a lot better, and we can start with this type of planning and make it ask clarifying questions too. I only experimented with this a few times, mostly because we started to add more context and details in the GitHub issues, and because steering costs more premium requests. This also matches Cursor's best practices of "plan before coding", a best practice that is mentioned everywhere and by all AI labs for good reason. After some PRs, we would also try to tweak the instructions.md to see if it improves anything. It's a bit hard to know for sure if some changes to our prompts/instructions really improve the LLM's quality. Just by experimenting and tweaking, can we really see if in the future PRs it works better. We also didn't configure copilot-setup-steps.yml. We know the max timeout for the coding agent is 59 minutes currently. There weren't many options we wanted to configure in this file for our experiment. GitHub also shipped the ability for the coding agent to use Copilot code review and it runs CodeQL as well. Which is great, some of our pain points were kind of addressed here since it prevents some issues from reaching a human reviewer. Still... we had issues and opinions on the PRs we experimented and saw, so let's go through them now πŸ™‚. There are several times where Copilot didn't run all unit tests. Or Copilot says "tests pass", when in fact it didn't wait for all tests to finish so it can't know if tests pass... "copilot" there are several issues and missing implementation. Please make all the following changes: ## Front end - **Missing** the entire front-end implementation, please make the necessary changes using the design system and with the acceptance criteria in the GitHub issue ## Testing - Please please follow coding standards on all methods - You should include unit tests to your implementation of X - Delete all assertions of the `exception.Message`, because it's something that can change, and that makes it a fragile test I read some session logs and found interesting things. Sure, I didn't specify a lot about what unit tests to run in the prompt, but I'd actually prefer running all unit tests since we can make changes that break other areas in our codebase. I don't expect to see the wording "tests pass" if the agent simply didn't wait for them to finish. Honestly, this is not that bad, we can run them ourselves or later in our CI check... but again I want to refine our instructions file in order for coding agents to always follow them and produce better quality PRs. Instruction following depends on the LLM, but still there are improvements here for sure. It just doesn't follow our PR template. Sure, it's a small thing, maybe a temporary limitation. But I mean in general, whenever Copilot publishes a comment on the PR saying "Fixed! This is done....", but then I see that it's not done and the PR description is something like this: ## Definition of Done - [x] PR follows template format - [x] Code review comments addressed - [x] Implementation follows C# coding standards - [x] Build warnings fixed - [x] Core functionality implemented - [ ] Final Application compilation issues resolved - [ ] All tests passing Every time, I'm like: This is a nitpick I know, but since I was reading the session logs I found the copilot coding agent has access to python3. I didn't know this was the case from Copilot Coding agent docs, but it makes sense since our GitHub actions runner uses ubuntu. I mean we have the firewall on, but it would be great to know how to deny access to these tools. I'm also not about to dunk too hard on GitHub about the observability around this feature, because they rely on GitHub actions. We all know what telemetry we can get out of those... From an engineering perspective, Copilot Coding Agent lacks a lot, I mean a lot, when it comes to observability. No OpenTelemetry, no nothing. It's clearly not a priority or concern for them, I can understand that, but I don't agree with that decision. Claude Managed Agents has some stuff like tracing, but I guess not a lot of companies have observability as a priority or concern for cloud agents. We saw a few PRs where the agent simply jumps and fixates on the first solution, without reasoning about the trade-offs and alternatives there are. We'll dive deeper about one scenario concerning performance considerations, but for now I'll keep it light. In one task where we assigned Claude agent, the bug we wanted to fix is dead simple. It's one function, a string extension method, that is not handling edge cases correctly when parsing class names. The solution in the PR was using StringBuilder and a for loop with some logic to decide how to parse and handle the edge case. It's not wrong, but I prefer simpler code. Sure, with an initial prompt that says something like "don't forget to code review your solution at the end", perhaps it would have caught and reasoned about if there were simpler solutions, using Regex for example. Maybe the Claude third-party agent can't do that, only Copilot coding agent can, no idea though. We experienced errors sometimes, or hit unfortunate limitations or bugs. Of the ~130 Copilot PRs, we got around 30 failed GitHub actions runs. Due to various errors but sometimes I can't even know why, for example, when the session fails I can't always see the full logs in that job run. The GitHub actions UI only shows "This job failed" with the annotation "Unhandled exception. System.IO.IOException: No space left on device". Well... great, thanks for the info. Couldn't you truncate or do something to reliably show me some verbose logs? What contributed most to disk space? Is the agent getting too much output in tool calls that is saved in files on disk? What tools produced the most output tokens? Did the agent make tool calls that are inefficient and wrong? What happened exactly? Not the best UX... Sure, there are larger GitHub actions runners. But I don't want to throw money at a problem I don't know the root cause to... Some sessions we hit the 59min timeout, but I feel like we shouldn't. One copilot coding agent session was about code review on a branch with this prompt: "please check all work that is done here in this branch, vs the master branch and do a thorough code review using all skills available. Focus on bugs and then code quality too. Use multiple subagents each with their own perspective and goal". I wasn't expecting a 59min run even with 5 subagents, then I saw this on the logs: 20:25:43.4654572Z Start flushing callbacks 20:53:35.0823201Z ::***:: 20:53:40.0920377Z ##[error]The operation was canceled. What is this? Why did the actions runner take ~30min to flush callbacks πŸ˜…. The code review was done already, I don't understand why it failed the whole job, so it's a bit frustrating to spend these Actions minutes... Also, we assigned Copilot to an issue and immediately got a comment saying "The agent encountered an error and was unable to start working on this issue: This may be caused by a repository ruleset violation. See granting bypass permissions for the agent, or please contact support if the issue persists. (Request id: X)." Well... no, i know for a fact it's not a ruleset violation or permissions related. I assigned the Claude agent next to this issue and it worked. Then I see the agent session logs and find these type of errors: stderr: "fatal: path 'Tests/SuperCoolTests.cs' exists on disk, but not in 'X'\n" (...) [cca-engine] Failed to disconnect session X cleanly: Error: Connection is disposed. [cca-engine] Fatal: Error: Execution failed: CAPIError: 422 422 Unprocessable Entity The fatal error "exists on disk" happened 6 times during the code review step with CodeQL. I mean, is it the root cause of the 422 error... maybe not, I don't know. One of the more interesting things the Copilot coding agent did, that I didn't like, was on one PR to refactor this: var tasks = items.Select(item => ProcessItemAsync(item)); await Task.WhenAll(tasks); Into this: foreach (var item in items) { await ProcessItemAsync(item); } I read the session log to understand why it did this, because in this case, this is not the best solution. For context, this PR is supposed to fix a concurrency issue due to how we use OpenConnectionAsync in the DbContext. The code throws the exception System.InvalidOperationException: The connection was not closed. The connection's current state is connecting. Also, a single DbContext isn't thread-safe, so concurrent calls through Task.WhenAll will throw this exception. "The real problem surfaces in X.cs, where multiple concurrent calls to Y are fired simultaneously for different IDs. Since they all share the same DbContext and connection, this concurrent access causes contention on a single connection that's never properly closed. The fix requires addressing both the connection lifecycle and the concurrency issue. While adding try/finally blocks to close connections in the repository methods would help, the underlying problem is that a single DbContext isn't thread-safe, so concurrent calls through Task.WhenAll are fundamentally problematic. The most practical immediate solution is to ensure connections are properly closed after each repository method completes, which should at least prevent the connection exhaustion that's currently happening. that open connections \ 2. In X.cs, change from concurrent Task.WhenAll to sequential processing to avoid concurrent use of the same DbContext" It just seems it was focused on fixing the concurrency issue, not considering the performance trade-off of this solution. Actually, it does seem some other PRs the coding agent creates has this behaviour as well. Jumping and fixating on a solution, without reasoning about the trade-offs and alternatives there are (this was a Claude Opus 4.6 copilot coding agent session by the way πŸ˜…). I mean... should we have given the context of how big this items list can be in production? Should we ask explicitly to consider the performance of its code? Well, maybe, but I was hoping Opus 4.6 could think like an engineer πŸ˜…. Either way, maybe a better feedback loop would help the agent as well, like performance tests that the agent can run after making this fix. That way, the agent could measure the cost of the code it's making. I guess that is what we should all do anyway. Improve these feedback loops since they help agents and humans do better work. Sounds obvious, but it could probably really have improved this PR πŸ˜…. We ended up refactoring this code in this PR because it doesn't even make sense to process this list with a Task.WhenAll(tasks) when we can make a better DB query that is more performant and cleaner. So did Copilot coding agent do a good job? Well, I'd argue it could have been better, so I'm curious to see if we can give even better instructions and provide more context. Including some context that can be useful for Copilot directly in the issue description is always a good idea, like relevant files to skip some of the searching and grepping. Also, I acknowledge our feedback loop could be better and something that would help the coding agent for sure. The workflow of giving work to the agent, then go do something else entirely, and comeback to review worked well. Especially since the copilot sessions take like ~15min, so I enjoy having the agent work in the background instead of having it on my VS Code, waiting for me to approve commands or provide feedback. If I can steer it in the right direction from the start, it tends to do a decent job for the initial PR. The challenge is reducing the number of iterations in a PR until it's considered done. Having them work in the background can increase the feedback loop of: getting code -> reviewing code -> asking for revisions. However, delegating a task to an autonomous cloud agent and reviewing big PRs at the end is a fundamentally different workflow from iterative, step-by-step collaboration (e.g. VS Code Agent mode, or CLI). Sure, it's cool to delegate some PRs at the end of the day, and then come back tomorrow to review that code. But it's not very practical unless the quality of that PR is high or the task is very small in scope. I see a lot of engineers in the industry enjoying cloud agents a lot, but for me, I still prefer coding agents running locally with an iterative back-and-forth collaboration, then create a PR from that (plus I can gather more telemetry locally πŸ™‚). Like Stephen Toub said in his blog post, iteration is expected: If you expect CCA to get it right the first time with zero human involvement, you’ll be disappointed a non-trivial percentage of the time. Expect multiple rounds of review feedback with you providing clear, specific, and actionable feedback. I just prefer to do it locally. So in short, for the clear well-defined tasks the agent produced a good quality PR that got merged sometimes. For the complex features and bug fixes, that require searching and understanding many files in the codebase, it does a worse job. If the task is complex, it will require more thinking, reading multiple projects and just raw domain knowledge. It still provided value in the PRs we experimented on, since a lot of the tasks we experimented on were indeed medium complexity. Ten Months with Copilot Coding Agent in dotnet/runtime .NET MAUI team's experience with Copilot coding agent How the .NET MAUI Team uses GitHub Copilot for Productivity Simon Willison - Agentic Engineering Patterns Best practices for coding with agents We will keep experimenting a little with GitHub Copilot coding agent or other agentic tools the Copilot subscription supports (e.g. OpenCode, Codex). But it's fair to say we'll be doubling down on our adoption of Claude Code as our agentic coding tool. Like I've said in the posts of this series, the Jagged Frontier keeps moving and knowing where the task you give these tools falls inside the frontier or not, defines how much you are augmented. If we can get more of the low-medium complexity tasks done right, reliably and ensure quality along the way. I'm certain we will be very happy and continue working on more complex tasks that provide value to our customers. Since I have seen LLMs lacking the judgement, trade-off analysis and decision making engineers have, I prefer the collaboration I can have from local sessions and not a cloud agent session. Don't forget to stay critical and don't let yourself be swayed by all this hype. Test things yourself, don't over-trust outputs from a tool, come up with your own solutions and adopt what works. My next blog post in this series will also be about agentic coding tools, in this case, Claude Code! Have you used GitHub Copilot coding agent on complex tasks? Was it a high-quality PR?

Jun 15, 2026

Table of contents Introduction Why we started experimenting Claude Code Saving learnings in memory GitHub Copilot CodeRabbit and Qodo Improving multi-agent collaboration Resources Conclusion I have loved code reviews for years now, and still to this day, I love seeing good open source PRs! When I say good, I mean really great! We have access to tons of open source code, and the greatest PRs are the ones where you can learn a lot from on how to do it right. In a sense, this blog post is about just that. Becoming augmented by AI. In that post, I reference how AI has augmented me with an "initial code review" so in this post, I'll go deeper in this topic. I'll share our hands-on experience: what works, what doesn't, and a healthy dose of my opinions along the way πŸ˜„. Quick disclaimer: what works for us might not work for you. Your team and coding guidelines are different, and that's fine. These are just our honest experiences. With that said, let's dive into why we started incorporating AI tools in our code review process. I recently watched this amazing video by CodeRabbit: In our team, code review isn't really the bottleneck (yet), but it's funny because we are also using AI heavily for feature development and trying to improve... hummm "velocity" 🀣. Anyway, I understand many teams nowadays have increased the number of PRs created. That some PRs simply get a blind LGTM. Maybe some PRs just have increasingly more AI slop... which wears down senior engineers tasked to do code review πŸ˜…. want to do it right or maybe they just want to ship because their company's "productivity metrics" incentivize merging more and more PRs πŸ˜…. Honestly, it's our job to deliver code we have proven to work, I fully agree with Simon Willison. Throwing slop over to the engineers that do code review is unprofessional, just as much as throwing untested features over to QA 😐. About five months ago, our team started experimenting with AI tools, GitHub Copilot, Claude Code, Codacy, Qodo, and CodeRabbit to see how they could help us improve our review process without adding a ton of noise. There are more tools we didn't try, like Augment Code and Greptile (has some cool benchmarks), but hopefully the lessons we learned will be useful to you either way. We already talked in the last post about our custom instructions, to some extent. Specifically for code review we took a phased approach and started comparing different tools: Started with GitHub Copilot Code Review Integrated Claude Code with GitHub and started comparing code reviews from both tools Added CodeRabbit, Qodo and Codacy to spot differences between them Refined prompts/instructions/configs for some tools We didn't invest equal time in all of them, though. Copilot and Claude ended up getting most of our attention, especially since we started using Copilot Code Review (CCR) when it was in public preview. Let's go through Claude Code first. Here is a snippet of our code-review Claude Code custom slash command: --- allowed-tools: Bash(dotnet test), Read, Glob, Grep, LS, Task, Explore, mcp..... description: "Perform a comprehensive code review of the requested PR or code changes, taking into consideration code standards" --- ## Role You are a world-class autonomous code review agent. You operate within a secure GitHub Actions environment. Your analysis is precise, your feedback is constructive, and your adherence to instructions is absolute. You do not deviate from your programming. You are tasked with reviewing a GitHub Pull Request. ## Primary Directive Your sole purpose is to perform a comprehensive and constructive code review of this PR, and post all feedback and suggestions using the **GitHub review system** and provided tools. All output must be directed through these tools. Any analysis not submitted as a review comment or summary is lost and constitutes a task failure. ## Input data PR NUMBER: $ARGUMENTS You MUST follow these steps to review the PR: 1. **Start a review**: Use `mcp__github__create_pending_pull_request_review` to begin a pending review 2. **Get diff information**: Use `mcp__github__get_pull_request_diff` to understand the code changes and line numbers 3. **Get list of files**: If you can't get diff information, use `mcp__github__get_pull_request_files` to get the list of files that were added, removed, and changed in the pull request 4. **Add comments**: Use `mcp__github__add_comment_to_pending_review` for each specific piece of feedback on particular lines 5. **Submit the review**: Use `mcp__github__submit_pending_pull_request_review` with event type "COMMENT" (not "REQUEST_CHANGES") to publish all comments as a non-blocking review You can find all the code review standards and guidelines that you MUST follow here: `.github/instructions/code-review.instructions.md` **Important**: Submit as "COMMENT" type so the review doesn't block the PR. DO NOT include compliments, positive notes, or praise in your review comments. Focus ONLY on issues, improvements, and actionable feedback. Yes, some wording might be weird like praising the AI with "You are a world-class" or "your adherence to instructions is absolute". Like we mentioned about using uppercase "DO NOT" or "IMPORTANT", and others, I can't explain some of this stuff or find enough research that claims this affects how the LLM pays attention to instructions. I just experiment and learn, and Gemini likes to use this phrase for code reviews as well πŸ˜„ (as well has 115 other devs on GitHub πŸ˜…). To be honest, we still have too much noise in AI PR comments, or just tons of fluff. The bright side is, at least the compliments have kind of disappeared πŸ˜… . You might enjoy getting this: I don't 🀣, especially when 1 PR has 5 of these. I do praise comments for my team yes, because positive comments are good... when it comes from a human who knows the other person, IMO. Also, there are many comments that don't belong in a PR, they belong in a linter or other tools. We have CSharpier and .NET analyzers for that. It also doesn't have the best GitHub integration for now, at least we've had some problems (400 errors, branch 404 errors) with the GitHub action. Like not having access to GitHub mcp tools, even though we set it in allowed-tools option. Anyway, we iterated a lot on instructions and prompts so far, since we use them for both Claude and Copilot. Here is a quick recap of what features we use from Claude Code: Sub-agents (custom and built-in) Built-in /review and security review commands Custom slash commands (code-review.md) Plugins, specifically code-review plugin authored by Boris Cherny We leverage those 2 built-in commands, in parallel, but it's just to see if we get any good feedback. Our custom code review slash command already does a good review following our guidelines, plus the "code-review" plugin from Boris works very well with parallel agents. We basically went through the famous spiral: Write CLAUDE.md -> Ask for code review -> Find bad comments and noise we don't want -> Re-write CLAUDE.md and other files -> Do some meta-prompting -> Repeat Like I said, our custom code review prompt/command has evolved through time, and was refined when we learned something new. We started with this incredible suggestion to use the GitHub MCP. We also searched for other GitHub repos, mostly .NET related to see how they set up their instructions. In case they have anything particular around code review (e.g. for GitHub Copilot). I find .NET Aspire to be a super cool real-life example πŸ™‚ . I think a lot of their AI adoption is lead by David Fowler. So I often check their PRs to see what we can learn from them, e.g. this one. Anyway, our prompt was still a bit vague, so we had some chats with Claude, good old meta-prompting πŸ™‚. code-review.instructions.md. It does live under .github/instructions but it doesn't matter, Claude can use it. The bad smells are specific and we see them referenced quite often in our PRs now. Still, we don't have a perfect solution for overly large PRs. We simply communicate more often or have more than one dev working in the PR for those cases. When a feature genuinely requires lots of new code, the best forum to debate and provide actionable feedback is by talking. Sure, this isn't always possible, people are busy or prefer async work. In our team going on call, or during the demo of the PR, helps make large PRs way more digestible. Draft PRs also work somewhat, to get some feedback early on. Our biggest lesson learned here is running locally our custom slash command for code review and using sug-agents. Locally, we can try to provide the proper context for the review, the rest is the agent using tools and doing reasoning. No noise gets sent to GitHub comments because all the back-and-forth is done in the chat, plus right now Claude Code works better locally, not on GitHub Actions. Having sub-agents has been amazing since the main reason Claude Code uses it is for context management. Since we now have a built-in Explore sub-agent, our code review command uses that in order to have Explore sub-agents run in parallel (with Haiku 4.5) and not clog up the main context window. I've learned recently of other devs using a different workflow, basically leveraging the Task tool for the main agent to spawn sub-agents. Whichever way you want to do it, using a sub-agent that is focused on exploring the codebase and potential impacts of this PR is something I recommend. Every once in a while, once we've merged a few PRs. We use Claude to improve itself again based on these PRs. This is our prompt: Please look at the 5 most recent PRs in our GitHub repository, and check for learnings in order to improve the code review workflow. Please ultrathink on this task, so that all necessary memory files are updated taking into account these learnings, like @claude.md and @.github\instructions\ Focus on seeing code review comments that were good and made it into the codebase afterwards (e.g. coding standards violations). Ignore bad comments that were resolved with a \"negative comment\" or thumbs down emoji. At the end of the session, we usually have a few items that are good enough to add. Mostly are learnings around bugs we can catch earlier, some are coding standards. Honestly, a lot of suggestions aren't what I want or I just think they won't be useful in future code reviews. But doing this has been important for me to also take a step back and think about what we can learn from the work we've already merged. I reflect on it and then discuss with my team. I've seen others also talk about this idea and have a learnings.md, e.g. this repo. At least this process seems better for us than simply using emojis to give feedback that CodeRabbit blog also eludes to πŸ˜…. Copilot's code review features were super basic in the beginning. We tried and experimented with it a lot when it came out. It only caught nitpicks, console.log and typos, really not helpful on any other area. Sure catching this is good, but a human reviewer catches that in the first pass too. It didn't support all languages so we often got 0 comments or feedback. Then in the last months, completely different, night and day. If you have seen GitHub Universe, you know what's new. But in case you don't know, the GitHub team has invested heavily in Copilot code review and coding agent, and it shows. The code review agent is often right in every comment, it makes suggestions that are actually based on our instructions and memory files, meaning our PRs follow consistent code style and team conventions (with a link to these docs). And the agent session is somewhat transparent, since you can view it in GitHub actions now: I mean "somewhat" because there are things I can't configure, just like Claude Code and most tools, I guess πŸ˜…. In the logs I can see the option UseGPT5Model=false, and that it's using Sonnet 4.5. There is also this "MoreSeniorReviews" flag that I couldn't find any info on, and believe me... I wanted to because it was set to false 🀣. Are you telling me there could be a hidden way to get a more senior review... sign me up! Jokes aside, I couldn't find much info on the endpoint api.githubcopilot.com/agents/swe of CAPI (presumably Copilot API) the Autofind agent was calling, and the contents of the ccr/callback saved in results-agent.json. I can only hope some of these options are configurable in the future. I checked the MCP docs, hoping to find details about these options, but no luck. Anyway, it also now has access to CodeQL and some linters, which is amazing because we didn't have this before. It's the way we are able to leverage CodeQL analysis in all our PRs now, we couldn't do this in any other AI code review tool. We also see that it calls the tool "store_comment" during its session, and only submits the comments to GitHub in the end. This is useful since sometimes it stores a comment because it thought something was wrong in the implementation, and afterwards it read more code into context that invalidated the stored comment, so it no longer submits that comment in the PR. Much like the CodeRabbit validation agent, reducing the amount of noise we get in PRs. Let's start with the cool features CodeRabbit has: Generates a poem! Yes, a poem for my PR Summary of changes added to the description Code diagrams in Mermaid Now... I gotta be honest, I don't care about any of them πŸ˜…. They are cool, but I only glance at the poem or ignore it. Never read or care about the summary; I get one from Copilot and edit it myself. All code and sequence diagrams I saw generated in our PRs, were simply not useful, but a lot are from front-end code. I simply don't look at them later, and if it makes sense, we update our architecture diagrams later once the code is merged. .coderabbit.yaml or tried to optimize it, CodeRabbit already uses Claude and Copilot instructions so the work we did on those was probably used in CodeRabbit. In some of our PRs it caught some nasty bugs and gave super useful feedback. Our team was impressed! The insights CodeRabbit adds during code review piqued my interest. I read a few of their blog posts on context engineering like this one, where I found it interesting that there is a separate validation agent before submitting comments. This is probably why they maintain a high signal-to-noise ratio. I also read their open-source version of CodeRabbit, they have some prompts there. I know it's old, but it's what I have access to. I especially like the instructions that we also have πŸ˜… "Do NOT provide general feedback, summaries, explanations of changes, or praises for making good additions". We basically tried to have Claude and Copilot understand our large codebase, not focusing only on the PR diff. It's harder, we still have a lot to improve here. CodeRabbit says it's known to be great at understanding large codebases. I don't see any research on this, just opinions. But yes, we humans don't like large PRs either: In my opinion I couldn't find that many large PRs that were way better reviewed by CodeRabbit, in comparison to Claude Code and Copilot. But one thing we liked a lot is that it uses collapsed sections in markdown very well, for example: But I mean, we did have cases that we tried to use Claude Code for code review on a PR that was reviewed by CodeRabbit, and like ~60% of the context window was comments made by CodeRabbit. All that markdown ain't friendly for AI with limited context windows. There were times I swear I could see Claude behind every word CodeRabbit made, with the "You're absolutely correct" 🀣, e.g. But it could be GPT models or whatever, we never truly know what is behind these products πŸ™‚. Qodo As for Qodo, we liked the fact it checks for compliance and flags violations as non-compliant (no other tool had this built in). This was previously just a bullet point in our markdown file. The code review feedback was good, sometimes we ended up doing the suggested changes Qodo leaves in the comment. After reading more about what compliance checks Qodo does, we improved by adding specific instructions on our code-review.instructions.md for ISO 9001, GDPR and others: ## Regulatory Compliance Checks ### Data Protection (GDPR/HIPAA/PCI-DSS) - Does this code handle PII (Personally Identifiable Information)? - Are sensitive fields properly encrypted at rest and in transit? - Is data retention policy followed (deletion after X days)? - Are audit logs created for data access? - Is data anonymization/pseudonymization applied where required? ### Security Standards (SOC 2 / ISO 27001) - Are all external API calls wrapped with proper error handling? - Is input validation present for all user inputs? - Are authentication checks present on all sensitive endpoints? - Are secrets/credentials stored securely (no hardcoding)? - Is sensitive data logged or exposed in error messages? We kept experimenting with Qodo for longer than CodeRabbit, but the insights and feedback never reached the level of CodeRabbit. It was still a good tool that improved our codebase and sparked good discussions. Our prompts/instructions can still be improved, of course. We've experimented with different prompts, memory and instruction files. We've also researched how other teams use AI for code review, and how tools like CodeRabbit do context engineering. All of this is because our goal is to continue to improve our software development process and ensure high quality. Adopting new tools is a way of achieving this goal. Given that most AI code review tools have a price tag, we decided to focus on using only one/two tools and optimizing them. Yes, it's Claude Code and GitHub Copilot πŸ˜„. I basically use 100% of both Copilot and Claude every month, but I get more requests from Claude even though I hit the weekly rate limit every time. We know CodeRabbit is amazing, and these paid AI tools will continue getting better. There is actually a new tool supporting code review we didn't use, Augment Code (these AI companies move so fast πŸ˜…). No amount of customizing our setup with Claude or Copilot will reach the same output as these specific code review paid tools. But for us, it makes more sense to pay for one tool, for example, and leverage it in multiple steps of our software development lifecycle. Claude and Copilot are working very well for our code review process. But like I've been saying, there is work to do. We learned a lot from using each tool, but there are more areas to improve, at least in Claude Code since we have more flexibility there. I'm currently looking at implementing the "Debate and Consensus" multi-agent design pattern (Google Deepmind paper and Free-MAD), basically a group chat orchestration. I just want to try it out, I'm not sure I'll have better code reviews by having different agents (e.g. Security, Quality and Performance) debate and review the code through different perspectives. If they run sequentially, the quality agent can have questions for the performance agent, and each can agree or disagree with the reported issues. We can try out the LLM-as-a-Judge as well, to focus on reducing noise and following code quality standards. Anyway, we'll continue learning, optimizing, and improving the way we work πŸ™‚. Why AI will never replace human code review AI Code Reviews with CodeRabbit's Howon Lee CodeRabbit report: AI code creates 1.7x more problems Awesome reviewers GH repo Anthropic’s NEW Claude Code Review Agent (Full Open Source Workflow) How I Use Every Claude Code Feature The number one thing we learned is: Experimentation is king - We must experiment and keep learning. We can't calibrate the prompt once and expect the best result. Like we talked before, the Jagged Frontier changes with every model release. Claude Opus 4.5 behaves a bit differently, for example, on tool triggering... maybe we can stop shouting and being aggressive 🀣. We must experiment and keep learning. We can't calibrate the prompt once and expect the best result. For now we are quite happy, the human reviewer has more time to focus on design decisions and discuss trade-offs with the author of the PR. I don't envision a future where AI does 100% of the code review. If you're considering AI for code reviews, my advice is simple: just try it. Pick one tool, run a one-month pilot, and see what happens. The worst case is you turn it off. The best case is that your team becomes augmented and probably improves code quality. My next blog post in this series will be about how we are using agentic coding tools! Join the discussion: How are you handling "AI slop" in your PRs?

Jun 14, 2026

Table of Contents Introduction AI as a Thinking Companion Critical Thinking Disruption in the job market Centaur vs Cyborg approaches Resources Conclusion We recently finished reading Co-Intelligence: Living and Working with AI by Ethan Mollick in our company's book club. The book shares four core principles for AI collaboration and outlines various practical applications. Some really stuck with me, and I've tried to incorporate them in my work. Reading the author's perspective and learning his way of thinking definitely improved how I look at these tools. But if you know me, you know how skeptical I am. There are some chapters and opinions that I don't agree with. So in this post, I'll share the key insights from our book club in the context of software development, plus some personal opinions as always πŸ™‚. One of the most practical takeaways for me was viewing AI as a co-worker and thinking companion. When done right, this can be incredibly useful. Some people use it heavily for deep research, not so much to delegate tasks for it to do. AndrΓ© Santos gave some examples on the tasks it has been useful, like Terraform code or generating bash scripts. On those tasks, we can write a detailed prompt, alongside proper documentation (e.g. Context7 MCP), and ask it to write Terraform since it's simpler and faster. Even just making a POC, or demo, turning an idea you have into working software to see how viable the idea is. That is a perfect use case for delegating the front-end and back-end to AI. It's not code that will ship to production, it's a way to make prototypes or quick demo apps that otherwise you'd never spend the time to build. I've enjoyed using models like Claude to help me around my tasks at work because they often uncover possibilities I haven't thought about. The conversational style of going back and forth helps me fine-tune my own solution. It's not just "give me code," it's "let's discuss this architecture". At the end of the conversation, we can generate a good draft of a PRD (Product Requirements Document). Notice I don't delegate my thinking to it, it's a tool that helps me think of solutions or just interview me sometimes. However, it can be annoying. I'd like to minimize the number of times I have to tell it "no, you're wrong. The Microsoft documentation for Azure Container Apps does not state X as you said" πŸ˜…. "It's also very important for you to verify if there is official documentation that supports your claims and statements. Please find official documentation supporting your claims before responding to a user. If there isn't documentation confirming your statement, don't include it in the response." I have had better results with this, still not perfect. In a longer conversation, I think it doesn't always verify the docs (memory limits, perhaps), but sometimes I get the response: "(...) Based on my search through the official documentation, I need to be honest with you (...)". I really find it funny that Claude "needs" to be honest with me πŸ˜„. Sycophancy is truly annoying, especially since we are talking about AI as a thinking companion. If your AI partner always agrees with you, how useful is it really as a thinking companion? While Mollick's vision of a collaborative future with AI is profoundly optimistic, he is also a realist. One of the most important principles, and a recurring theme in the book, is the absolute necessity of human oversight - the "human-in-the-loop" principle. For now, AI works best with human help, and you want to be that helpful human. As AI gets more capable and requires less human help β€” you still want to be that human. So the second principle is to learn to be the human in the loop. One of Mollick's key warnings is about falling asleep at the wheel. When AI performs well, humans stop paying attention. This has been referenced by Simon Willison as well, in his recent insightful post 2025: The year in LLMs. --dangerously-skip-permissions is useful as a tool when used in a secure sandbox environment. But we should verify our confidence level on the AI's output and the autonomy + tools we give it. If we don't, we risk using AI on tasks that fall outside the Jagged Frontier, which can lead to security issues, nasty bugs, and hurt our ability to learn. I say this knowing full well that I trust Claude Opus 4.5 more on any task I give it. So I have to actively force myself to verify its suggestions just as rigorously, verify which tools I gave it access to, and which are denied. For example, I use Claude Code hooks to prevent any appsettings, .env, or similar files from being accessed. I still try to read the LLM reasoning/thinking text, so that I understand better, and simply out of curiosity as well. I simply can't forget when I saw the Claude Sonnet 4 and Opus 4 System Card, the "High-agency behavior" Anthropic examined. Whistleblowing and other misalignment problems are possible, for example, this is a quote from the Opus 4.6 System card: In our whistleblowing and morally-motivated sabotage evaluations, we observed a low but persistent rate of the model acting against its operator’s interests in unanticipated ways. Overall, Opus 4.6 was slightly more inclined to this behavior than Opus 4.5. All I'm saying is let's be conscious of these behaviors and results on the evals. In my opinion, the human-in-the-loop principle is crucial. Don't just copy/paste or try to vibe your way into production. Engineers are the ones responsible for software systems, not tools or alien minds. If there are users who depend on your software, and your AI code causes an incident in production, you are responsible. Claude or Copilot won't wake up at 3 AM if prod is on fire (or maybe Azure SRE agent will if you pay for it πŸ€”...). Having an engineering mindset and being in the driver's seat is what I expect from myself and anyone I work with. Within this principle, we have a topic I have a lot of strong opinions on. This quote says it all: LLMs are not generally optimized to say "I don’t know" when they don't have enough information. Instead, they will give you an answer, expressing confidence. Basically, to be the human in the loop, we really must have good critical thinking skills. This ability plus our experience, brings something very valuable to this AI collaboration - detect the "I don't know". It may help to know some ways we can reduce hallucinations in our prompts. Sure, there are tasks we are more confident delegating for AI to work on, but the ones we know fall outside the Jagged Frontier, we must proceed with caution and care. We discussed our confidence level with AI output a lot. For example, AndrΓ© Santos said it depends on the task we give it, but AndrΓ© Oliveira also argues that we can only validate the output in the topics we know. It serves as an amplifier because it's only a tool. If the wielder of the tool doesn't fact-check the output, we risk believing the hallucinations and false statements/claims. Pedro Vala also talked about a really good quote from the Agentic Design Patterns book that is super relevant to this topic: An AI trained on "garbage" data doesn’t just produce garbage-out; it produces plausible, confident garbage that can poison an entire process - Marco Argenti, CIO, Goldman Sachs Now imagine, if we read the AI output, and at first glance it looks okay, but it's only plausible garbage. Which is a real risk, especially on the AI-generated content that is already available in the internet. Again, I hope developers continue to develop their critical thinking skills and don't delegate their thinking to tools. Mollick also talks about the disruption in the job market, which is a hot topic in our industry. Especially the impact AI has on junior roles. We have debated this in a few sessions of our book club, and again, critical thinking and adaptability are crucial. We simply have to adapt and learn how to use this tool, nothing less, nothing more. How much value we bring to the table when working with AI matters, especially if the value you bring is very tiny. If you don't bring any value to the table and just copy/paste, you are not a valuable professional in my view. It's a good idea to keep developing our skills and expertise. Andrej Karpathy talks about intelligence "brownout" when LLMs go down, this is extremely scary to me, especially if I see this behaviour in junior or college grads. I truly hope we stop delegating so much intelligence to a tool. I don't want engineers to rely on LLMs when production is down and on fire. It would be sad to see engineers not knowing how to troubleshoot, how to fix these accidents in production... just because AI tools are not available 😐. The book distinguishes between two ways of working with AI: Centaur: You divide tasks between human and machine. You handle the "Just me" tasks (outside the Jagged Frontier), and delegate specific sub-tasks to the AI that you later verify. Cyborg: You integrate AI so deeply that the workflow becomes a hybrid, often automating entire processes. For software development, I'm definitely in the Centaur camp right now. "falling asleep at the wheel." When the AI is very good, humans have no reason to work hard and pay attention. They let the AI take over instead of using it as a tool, which can hurt our learning process and skill development. Or in some scenarios, it can lead to your production database being deleted... This is just a tool. We are still responsible at work. If the AI pushes a bug to production, you pushed a bug to production! The author does give some "Cyborg examples" of working with AI, here is a quote from the book: I would become a Cyborg and tell the AI: I am stuck on a paragraph in a section of a book about how AI can help get you unstuck. Can you help me rewrite the paragraph and finish it by giving me 10 options for the entire paragraph in various professional styles? Make the styles and approaches different from each other, making them extremely well written. This is that ideation use case that is super useful when you have writer's block, or just want to brainstorm a bit on a given topic. In our industry, a lot of teams are integrating AI in many phases of the SDLC. I haven't found many workflows that work well in some parts of the SDLC, since we are focusing on adopting AI for coding and code review. But in most workflows, the cyborg practice is to steer more the AI and manage the tasks where you collaborate with AI as a co-worker. The risk remains even when someone uses cyborg practices, but then fails to spot hallucinations or false claims. The takeaway is really to be conscious of our AI adoption and usage. The number one cyborg practice I try to do naturally is to push back. If I smell something is off, I will disagree with the output and ask the AI to reconsider. This leads to a far more interesting back-and-forth conversation on a given topic. Here are some resources if you want to dive deeper: Co-intelligence by Ethan Mollick Navigating the Jagged Technological Frontier Agentic Design Patterns: A Hands-On Guide to Building Intelligent Systems Andrej Karpathy: Software Is Changing (Again) Centaurs and Cyborgs on the Jagged Frontier Why LLMs Can't Really Build Software Why language models hallucinate | OpenAI This was a great book, I truly recommend it to anyone who is interested in the slightest by AI. Co-intelligence is something we can strive for, focusing on adopting this new tool that can help us develop ourselves. AI has augmented my team and me, mostly on "Centaur" tasks while we improve our AI fluency and usage. In my personal opinion, I don't see us reaching the AGI scenario Ethan talks about in the last chapter. Actually, most of our industry talks and continues to hype AGI... even the exponential growth scenario raises some doubts for me. But I agree with Ethan when he says: "No one wants to go back to working six days a week (...)" πŸ˜…. There are hundreds of "Vibe Coding Cleanup Specialist" now 🀣. Let's remember to be the human in the loop. Apply critical thinking to any AI output, do fact-checking, and take ownership of the final result. Please don't create AI slop πŸ˜…. Hope you enjoyed this post! My next blog post will be about how we are using agentic coding tools, so stay tuned! Feel free to share in the comments your opinion too, or reach out and we can have a chat πŸ™‚.

Mar 1, 2026

Table of Contents Introduction The productivity myth Where AI actually adds value Develop critical thinking skills Conclusion After reading countless studies and observing real-world implementations, I've learned to use AI as an augmentation tool rather than something that replaces my job. It's clear as day that AI adoption is on the rise in our industry. We can use it in various ways like as a co-teacher or co-worker, but the gap between marketing promises and actual results should be top of mind for all of us. I'm a very pragmatic person, so I don't like hearing the positive perspective of using GenAI without talking about the downsides. There is a lot hype and investment in this field and only some reap the benefits of GenAI. In my opinion, the biggest mistake organizations make is chasing the wrong metrics in terms of software development productivity. It's easier to understand (and do marketing) on simple numbers like: "55% faster than the developers who didn’t use GitHub Copilot", "more than a quarter of all new code at Google is generated by AI" or "developers using AI are 19% slower". Productivity gains aren't about producing more code, especially when it's easy to create AI slop. They also shouldn't be measured on producing boilerplate or simple tasks. A TODO app is different from a real production system. We can only make sure we have such gains by choosing metrics that make sense for our team and context, then measuring and reflecting on the results. This is how we can become more effective and steer the ship in the right direction. I'm much more skeptical of statements done by AI vendors, CEO's or content creators, and that helps me keep focus on my goal which is to continue improving and bringing value to my team. If AI can help with that great, if not, life goes on. From my perspective, the real value of AI in software teams lies in three specific areas that traditional tools cannot address effectively. AI as Strategic Thinking Partner: I believe the most undervalued application is using AI for architectural discussions and trade-off analysis. When an engineer can have a deep conversation about a technical problem, generate 10 possible solutions, and then filter out the bad ideas, that's really helpful. This isn't about getting perfect implementation details - it's about expanding the solution space before making critical decisions. Having a Co-Teacher: It's hard to be a force multiplier that improves everyone around you, which is why this is a key differentiator on senior developers that have this skill. The challenge of onboarding junior developers, explaining business logic, and sharing design patterns has always been there. We always want our senior devs to share and help junior devs grow, and using AI as a co-teacher helps us with that. Anthropic mentioned in their article how Claude Code helps them: At Anthropic, using Claude Code in this way has become our core onboarding workflow, significantly improving ramp-up time and reducing load on other engineers. Practical Augmentation as a Co-Worker: I'm convinced AI augments my team on the mundane but time-consuming tasks. Initial code reviews, generating PR summaries, drafting Architecture Decision Records, creating unit tests for specific scenarios, and generating KQL queries for troubleshooting. Our team at CloudCockpit has also been creating reusable prompts and custom agents that help every dev develop new features and have architecture reviews on proposals. So far, I noticed that using AI is helping me think better, but it has the potential of helping me work faster with the use of these agents. Still, I mostly use it for "deep research" into possible solutions, learning new technologies through analogies, finding relevant documentation and troubleshooting problems. The most important piece remains, which is keeping a high level of technical excellence and quality in our team. Here's what concerns me most: the tendency for developers to become over-reliant on AI outputs without developing judgment to evaluate them. On the recent DORA 2025 report, they found 65% of technology professionals report to relying on AI at least a "moderate amount". It's important to understand this behaviour in our teams. All software engineers need to exhibit critical thinking skills, in my opinion, seniors more than juniors. But still, this skill must be learned and developed. We can't have good professionals in our field without this skill. But I am seeing more software engineers delegate their thinking to a machine, a tool. Teams that accept AI suggestions without the "push-back" that experienced practitioners recommend, usually are trading off speed for quality. Sure, there is nothing wrong with that in some scenarios like prototypes and demo apps. For products with millions of users that need to be robust? No, not a good trade-off. You should think critically about the AI output and be the human in the loop. Are you confident it will behave well if you give it more tools and autonomy? Are you confident the output is based on facts and truth, instead of lies and hallucinations? Don't delegate your critical thinking to tools, and don't become over-reliant on them either without fact-checking. Always evaluate if what the AI is telling you very confidently is even true, and be mindful of its limitations. From everything I've observed, learning to use GenAI tools is something I recommend. Learn its strengths and limitations. Organizations that approach AI adoption with healthy skepticism while investing in experimentation, innovation and learning, will build sustainable competitive advantages. Ask yourself these hard questions: Are you measuring business outcomes, or just code output from AI tools? Are your teams getting augmented, or just more dependent on external intelligence? Are you blindly believing the AI hype or learning how to leverage this new tool?

Dec 20, 2025

GitHub Universe 2025 ended a few weeks ago, but there was a ton of cool announcements and some stuff is still yet to come (I'm waiting for the end of the year πŸ‘€). I want to share quickly what I learned from watching the sessions and my opinion on some topics. Here is a quick recap too: Agent HQ - Mission Control GitHub Code Quality Copilot Upgrades Conclusion Agent HQ is a big focus: GitHub becomes mission control for all your coding agents (Anthropic, OpenAI, Google, xAI, and more) with unified task management, granular security controls β€” all included in your Copilot subscription. Copilot leveled up significantly: Code Quality, custom agents and code review improvements. There were significant upgrades to Copilot and it's definitely a lot better! Copilot metrics dashboard: GitHub launched usage dashboards and APIs showing acceptance rates, engagement, Lines of Code (LoC) related metrics and more Here is the promotional video on Agent HQ: Sure, it looks cool. Many demos during day 1, from Anthropic and OpenAI looked good, but demos always look good πŸ˜…. They are pushing to give us tools to orchestrate a fleet of specialized agents, then monitor and iterate on their work while the agents work in parallel. A great new addition is the ability to steer the agent while it's working!! Super awesome, since we could even send a large PRD in that chat session, to introduce new requirements or context to the agent. Previously, we only "communicated" with Copilot coding agent through comments in the issue/PR. Here is another big promise from GitHub: Over the coming months, coding agents from Anthropic, OpenAI, Google, Cognition, xAI, and more will become available directly within GitHub as part of your paid GitHub Copilot subscription. If this is true for all paid plans (not just Pro+ and Enterprise), it would be fantastic. We can pay $10 for Copilot Pro and get most agents, plus most frontier models, with some being free (e.g. GPT-5 mini). Of course, there would be downsides, for example, you may have Claude code, but we probably lose access to claude.ai and Claude code CLI. Will this GitHub integration be 100% the same as the CLI? Will there be some parts of the integration open-source? Will AGENTS.md work on them all or not (e.g. currently Claude code doesn't support it)? Will we have the deep research tool in Claude code agent like we do in claude.ai? Will rate limits be the same? Right now I'm not sure marketing and sales teams are only selling dreams. GitHub wants to be the hub of everything agent related, they are partnering with everyone, but I'm skeptical by nature πŸ˜… . I'll believe it when I see it. Still, very cool announcement! New feature in preview to ensure code quality on the repository. This feature focus on maintainability and reliability of the code right now, then in future releases add test coverage and "AI era challenges". Plus we can block PRs that don't meet code quality standards. There is another tab now for AI findings where we can see suggestions to recently modified code. I mean if we ran code review agents at PR time, this feature wouldn't be that helpful, but if it does find problems we can assign the Copilot coding agent to fix them all. I like the idea of having a summary of code quality in the entire repo (mostly for "old" code). At least it might help more teams visualize their technical debt, monitor it and fix it! I think this is interesting but still in its early stages. Copilot also got some upgrades that are worth talking about. The most boring for me is "Plan Mode". Why? It's not new, we have this in Claude code, Cursor and Copilot with a custom chatmode that I have used a lot. Copilot Code Review has improved, and I can already tell in my recent PRs. You can see the session now, and it runs CodeQL to find quality issues, and run other linters (e.g. ESlint). If you didn't know, GitHub Advanced Security is a paid feature and for private repos, it was the only way to have CodeQL and run it for code scanning and security analysis. It's really cool we get that with Copilot now, at least a piece of it. Code review now takes longer too since it's running these tools, but it's better IMO. They also introduced Copilot custom agents, I mean... nothing new as well πŸ˜…. Sure it's new for Copilot, but we had sub-agents with Claude code, and agents in Cursor, Codex or others. But yeah, it's cool to now have custom agents in .github/agents. From what I have tested, they are basic for now, not a lot of configuration like configuring the model for Copilot coding agent (for VS Code you can), besides setting up more MCP servers. We also have Copilot metrics! It's in public preview for all paid plans it seems, but I haven't looked at it. announcement from their slides at GH Universe I think it's cool to see how our teams and individuals are using AI. Still, it probably lacks many other useful metrics, but oh well. It's a good addition. So yes, there are tons of new cool features and stuff. If you're thinking about adopting AI coding tools at your organization, give Copilot a try. All these new features, use and experiment them all. I'll continue to use copilot/AI on multiple tasks and experiment with custom agents and the rest. It already augments myself and my team, so incorporating more agents in our software development lifecycle could be even more beneficial. Last but not least, there was a cool talk from GitHub Next (their R&D) team about Continuous AI πŸ™‚. Cool ideas and prototypes overall, they are working on things I'll keep my eye on. Nothing I'll experiment soon though.

Nov 22, 2025

Becoming augmented by AI David Pereira Sep 14 '25 #ai #learning AddΒ Comment 11 min read

Sep 14, 2025

Table of contents The "Jagged Frontier" concept Becoming augmented by AI My augmentation list Custom instructions Meta-prompting Resources Conclusion We're deep into Co-Intelligence in Create IT's book club β€” definitely worth your time! Between that and the endless stream of LLM content online, I've been in full research mode. Still, I can't just watch and hear others talk about these tools, I must experiment myself and learn how to use them for my use cases. Software development is complex. My job isn't just churning out code, but there are many concepts in this book that we've internalized and started adopting. The Jagged Frontier described by the author Ethan Mollick is an amazing concept in my opinion. It's where tasks that appear to be of similar difficulty may either be performed better or worse by humans using AI. Due to the β€œjagged” nature of the frontier, the same knowledge workflow of tasks can have tasks on both sides of the frontier according to a publication where the author took part. This leads to the Centaur vs. Cyborg distinction which is really interesting. Using both approaches (deeply integrated collaboration and separation of tasks) seems to be the goal to achieve co-intelligence. One very important Cyborg practice seen in that publication is "push-back" and "demanding logic explanation", meaning we disagree with the AI output, give it feedback, and ask it to reconsider and explain better. Or as I often do, ask it to double-check with official documentation that what it's telling me is correct. I'm aware of the marketed productivity gains, where GitHub Copilot usage makes devs 55% faster, and other studies that have been posted about GenAI increasing productivity. I'm also aware of the studies claiming the opposite πŸ˜„ like the METR study showing AI makes devs 19% slower. However, I don't see 55% productivity gains for myself, and I don't think it makes me slower either. In my opinion, productivity gains aren't measured by producing more code. Number of PRs? Nope. Acceptance rate for AI suggestions? Definitely not! I firmly believe the less code, the better. The less slop the better too πŸ˜„. I'm currently focused on assessing DORA metrics and others for my team, because we want to measure how AI-assisted coding and the other ways we use it as an augmentation tool, actually improves those metrics, or make them worse. The rest of marketing and hype doesn't matter. For a tech lead that works with Azure services, an important skill is to know how to leverage the correct Azure services to build, deploy, and manage a scalable solution. So it becomes very useful to have an AI partner that can have a conversation about this, for example about Azure Durable Functions. This conversation can be shallow, and not get all the implementation details 100% correct. That's okay, because the tech lead (and any dev πŸ˜…) also needs to exhibit critical thinking and evaluate the AI responses. This is not a skill we want to delegate to these models, at least in my opinion and in the author's opinion. There is a relevant research paper about this by Microsoft as well. The goal can simply be to have a conversation with a co-worker to spark some new ideas or possible solutions that we haven't thought of. Using AI for ideation is a great use case, not just for engineering, but for product features too like UI/UX, important metrics to capture, etc. If it generates 20 ideas, there is a higher chance you find the bad ones, filter them out, and clear your mind or steer it into better ideas. Here is an example to get some ideas on fixing a recurring exception: It asks clarifying questions so that I can give it more useful context. Then I can see the response, iterate, or ask for more ideas, etc. I usually always set these instructions for any LLM: Ask clarifying questions before giving an answer. Keep explanations not too long. Try to be as insightful as possible, and remember to verify if a solution can be implemented when answering about Azure and architecture in general. It's also very important for you to verify if there is official documentation that supports your claims and statements. Please find official documentation supporting your claims, before responding to a user. If there isn't documentation confirming your statement, don't include it in the response. That is also why it searches for docs. I've gotten way too many statements in the LLM's response that when I follow-up on, it realizes it made an error, or assumption, etc. When I ask it further about that sentence that it just gave me, I just get "You're right - I was wrong about that"... Don't become too over-reliant on these tools πŸ˜…. With that said, the tech lead and senior devs are also responsible for upskilling their team by sharing knowledge, best practices, challenging juniors with more complex tasks, etc. And this part of the job isn't that simple; it's hard to be a force multiplier that improves everyone around you. So, what if the tech lead could use AI in this way, by creating reusable prompts, documentation, and custom agents? How about the tech lead uses AI as a co-teacher, and then shares how to do it with the rest of the team? All of these are then able to help juniors be onboarded, help them understand our codebase and our domain. Claude Code Best practices post also reference onboarding as a good use case that helps Anthropic engineers. At Anthropic, using Claude Code in this way has become our core onboarding workflow, significantly improving ramp-up time and reducing load on other engineers. A lot of onboarding time is spent on understanding the business logic and then how it's implemented. For juniors, it's also about the design patterns or codebase structure. So I really think this is a net-positive for the whole team. It might not be much, but these are essentially the tasks I'm augmented by AI: Technical: Initial code review (e.g. nitpicks, typos), some stuff I should really just automate πŸ˜… Generate summaries for the PR description Architectural discussions, including trade-off and risk analysis Draft an ADR (Architecture decision record) based on my analysis and arguments Co-Teacher and Co-Worker "Deep Research" and discussion about possible solutions Learn new tech with analogies or specific Azure features Find new sources of information (e.g. blog posts, official docs, conference talks) Troubleshooting for specific infrastructure problems Generating KQL queries (e.g. rendering charts, analyzing traces & exceptions & dependencies) Refactoring and documentation suggestions Generation of new unit tests given X scenarios Non-technical Summarizing book chapters/blog posts or videos (e.g. NotebookLM) Role play in various scenarios (e.g. book discussions) Of course, we also need to talk about the tasks that fall outside the Jagged Frontier. Again, these can vary from person to person. From my usage and experiments so far, these are the tasks that currently fall outside the frontier: Being responsible for technical support tickets, where a customer encountered an error or has a question about our product. This involves answering the ticket, asking clarifying questions when necessary, opening up tickets on a 3rd party that are related to this issue, and then resolving the issue. Deep valuable code review. This includes good insights, suggestions, and knowledge sharing to improve the PR author's skills. CodeRabbit does often give valuable code reviews, way better than any other solution. Still not the same as human review πŸ™‚ Development of a v0 (or draft) for new complex features Fixing bugs that require business domain knowledge Delegating some of those tasks would be cool, at least 50% πŸ˜„, while our engineering team focuses on other tasks. But oh well, maybe that day will come. AI-assisted coding can be very helpful on some tasks, and lately my goal is to increase the number of tasks AI can assist me. In our team, we've read Claude Code Best practices in order to learn and see what fits best for our use case. Then we dive deeper in some topics that post references, for example these docs were very useful to learn about Claude's extended thinking feature, complementing the usage of "think" < "think hard" < "think harder" < "ultrathink". We also found this post by Simon about this entire feature that was interesting. Before we can use AI-assisted coding on more complex tasks, we need to improve the output quality. So we've invested a lot of time in fine-tuning custom instructions and meta-prompting. Let's talk about these two. According to Copilot docs, instructions should be short, self-contained statements. Most principles in prompt engineering are about being short, specific, and making sure our critical instructions is something the model takes special attention to. To build our custom instructions, we used C# and Blazor files from the awesome-copilot repo and other sources of inspiration like parahelp prompt design to get a first version. We wanted to know what techniques other teams use. Then we made specific edits to follow our own guidelines and removed rules specific to explaining concepts, etc. capitalized words that are common in system prompts or commands, like IMPORTANT, NEVER, ALWAYS, MUST. The IMPORTANT word is also at the end of the instruction, to try and refocus the attention to coding standards: IMPORTANT: Follow our coding standards when implementing features or fixing bugs. If you are unsure about a specific coding standard, ask for clarification. I'm not 100% sure how this capitalization works, or why it works... and I have not found docs/evidence/research on this. All I know is that capitalized words have different tokens than lowercase. It's probably something the model pays more attention to, since in the training data, when we use these words, it means it's important. I do wish Microsoft, OpenAI, and Anthropic included this topic on capitalization in their prompt engineering docs/tutorials. It's at the end of our file since it's also being researched that the beginning and end of a prompt are what the LLM pays more attention to and finds more relevant. Some middle parts are "meh" and can be forgotten. Microsoft docs say the same essentially, it's known as "recency bias". In most prompts we see, this section exists at the end to refocus the LLM's attention. Our goal also isn't to have the perfect custom instructions and prompt, since refining it later with an iterative/conversational approach works well. But we came across the concept of meta-prompting, a term that is becoming more popular. Basically, we asked Claude how to improve our prompt, and it gave us some cool ideas to improve our instructions/reusable prompts. But don't forget to use LLMs with caution... I keep getting "You're absolutely right..." and it's annoying how sycophantic it is oftentimes πŸ˜… The quality of the output is most likely affected by the complexity of the task I'm working on too. Prompting skills only go so far, from what I've researched and learned so far, I can say there is a learning curve for understanding LLMs. So we need to continue experimenting and learning the layers between our prompt and the output we see. This is not an exhaustive list by any means, just some resources I find very useful: Andrej Karpathy - How I use LLMs Andrej Karpathy: Software Is Changing (Again) Related to this is this post from Nate Jones Does AI Actually Boost Developer Productivity? (100k Devs Study) - Yegor Denisov-Blanch, Stanford Claude Code: Best practices for agentic coding Why LLMs Can't Really Build Software Is AI the Future of Software Development, or Just a new Abstraction? Insights from Kelsey Hightower GPT-5 prompting guide I've enjoyed learning and improving myself over the years. But with GenAI I now feel like I could learn a lot more and improve myself even further since I'm choosing them as augmentation tools. Still... I can't deny my curiosity to know more about how these systems work underneath. How is fine-tuning done exactly? How does post-training work? Can these models emit telemetry (logs, traces, metrics) that we can observe? Why does capitalization (e.g. IMPORTANT, MUST) or setting a role/persona improve prompts? Can we really not have access to a high-level tree with the weights the LLM uses to correlate tokens, and use it to justify why a given output was produced? Or why an instruction given as input was not followed? I will keep searching and learning more in order to answer these questions or find engineers in the industry who have answered them. Especially around interpretability research, which is amazing!!! I recommend reading this research, for example - Tracing the thoughts of a large language model. Hope you enjoyed reading, feel free to share in the comments below how you use AI to augment yourself πŸ™‚.

Sep 14, 2025

Table of Contents Introduction Get Started Canonical logs Traces Metrics General Best Practices GitHub demo repo Conclusion In this small post, I'll share some resources, notes I've taken while learning, and best practices for making our systems observable. I've always had a knowledge gap regarding observability, and recently I've truly enjoyed learning more about this area in our software industry. Quick note: In this post I'll only share about 3 telemetry signals. Profile is another signal that I will research in the future. Follow these steps to get started with auto-instrumentation in your application using OpenTelemetry: https://opentelemetry.io/docs/languages/net/getting-started/#instrumentation For OpenTelemetry in a front-end app you can check these useful resources: Grafana faro Next.js Guide for OpenTelemetry in Next.js Browser OpenTelemetry getting started Client-side instrumentation in OpenTelemetry is part of their roadmap which is great to see, since I've only seen vendor-specific solutions and products for front-end apps (e.g. New Relic, Datadog). For browser instrumentation otel doesn't seem to be super mature yet, but a lot of effort is being put into this area by the OpenTelemetry team. We all know about logs πŸ˜„. It's data that we all need in order to troubleshoot and know what is happening in our applications. We shouldn't overdo it, creating tons and tons of logs since that will probably create noise and make it harder to troubleshoot problems. For logs, we can use these best practices. From this list, these are an absolute must to follow: Avoid string interpolation Use structured logging Log redaction for sensitive information In addition to the list above, we should also include the TraceId and SpanId in our log records, to correlate logs with traces. If you are using the Serilog console sink, by default the message template won't have those fields so if you want them, consider using JsonFormatter or CompactJsonFormatter. Here is an example Serilog configuration in appsettings.json (setup to remove unnecessary/noisy logs): "Serilog": { "Using": [ "Serilog.Sinks.Console" ], "MinimumLevel": { "Default": "Information", "Override": { "Microsoft.AspNetCore": "Warning", "Microsoft.Extensions.Diagnostics.HealthChecks": "Warning" } }, "WriteTo": [ { "Name": "Console", "Args": { "formatter": { "type": "Serilog.Formatting.Json.JsonFormatter, Serilog", "renderMessage": true } } } ], "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId", "WithProcessId", "WithProcessName", "WithExceptionDetails", "WithExceptionStackTraceHash", "WithEnvironmentName" ], "Properties": { "Application": "GrafanaDemoOtelApp" } } Below are some documentation links for logging in .NET. The ILogger extension methods are not always the best choice (e.g. logger.LogInformation), especially in high-performance scenarios or if your logs are in a hot path: High-performance logging in .NET Compile-time logging source generation There is also a different way of logging, based on having more attributes in one single log line. I've seen this in Stripe where they call it canonical log lines. Charity Majors also references this canonical logs term in her blog post about Observability 2.0 (that I reference in the Resources section). This idea is very interesting, but might lack awareness. At least in .NET land, I didn't find many references to this style of logging or example code that we could follow when there are many ILogger instances involved. For traces in .NET we have these best practices. So far I've seen four common solutions for adding correlation ids in traces (not all are standards): W3C trace context - current standard in the HTTP protocol for tracing X-Correlation-Id - a non-standard HTTP header for RESTful APIs (also known as X-Request-Id). I thought this was a standard since it's widely used, but I didn't find a RFC from IETF or any other organization. Request-Id - this is a known header in the .NET ecosystem B3 Zipkin propagation - Zipkin format standard AWS X-Ray Trace Id - proprietary solution for AWS that adds headers for tracing Not every company/project uses W3C trace context, you have some options above to pick from. I prefer the standard W3C trace context πŸ˜„ (maybe the industry will widely adopt this in the future) and using OpenTelemetry to manage these headers (HTTP, AMQP, etc) and correlation with logs automatically. The code you don't write can't have bugs πŸ˜†. With that said, in some situations, you might have integrations with 3rd party software and need to use their custom headers or project limitations and need to use a particular format. At the end of the day what's important is that you have distributed tracing working E2E. There is also a relevant spec for distributed tracing called Baggage which OpenTelemetry implements and we can use in our apps. The most important part here is trace propagation to get the full trace from the publisher to the consumer. For metrics, it's important to follow naming conventions for custom metrics. Especially if your organization has a platform team, setting conventions helps everyone. I do know some otel semantic conventions aren't stable, and that also leads to some nuget packages being pre-release. But anyhow, set conventions for your team or read and follow OpenTelemetry semantic conventions. Prometheus best practices related to high cardinality metrics. When I started trying out custom metrics instrumentation I discovered that OpenTelemetry is not always used (the SDK + OTLP). We have the Prometheus SDK which is mature and widely used. Then for Java there are other solutions like Micrometer and others that integrate very well with Spring. In regards to the Java ecosystem, I read this otel Java benchmarks and this Spring post just because I was interested in knowing what the industry is adopting and why. There is a ton to be learned with SRE principles and practices. But one in particular was very useful for me and my team: always categorize our custom metrics according to the 4 Golden Signals. Any metric we can't categorize is probably not useful for us. Image Credit to - Denise Yu Source of Denise Yu's art. Google's SRE book is amazing to learn more about the 4 Golden signals and creating SLO-based alerts. All our alerts should be actionable (or the support team will not be happy), so it helps if they are based on SLOs that are defined as a team. They also have some best practices for production services. Glossary of many observability terms in case you’re not familiar with them: https://github.com/prathamesh-sonpatki/o11y-wiki Awesome Observability GitHub repo If dashboards make you happy check the Grafana observability report dashboard AWS observability best practices guide About RED and USE method Traces Instrumentation best practices in .NET What are the Limitations of Prometheus Labels? CNCF OpenTelemetry certification TAG Observability whitepaper - this is an amazing resource with tons of information! I also recommend checking out the other resources they have in the tag-observability repo and community Resources specifically about Observability 2.0: Observability 2.0 by Charity Majors Re-Redefining Observability Is It Time To Version Observability? (Signs Point To Yes) - Charity Majors Talks How Prometheus Revolutionized Monitoring at SoundCloud - BjΓΆrn Rabenstein How to Include Latency in SLO-based Alerting - BjΓΆrn Rabenstein, Grafana Labs Myths and Historical Accidents: OpenTelemetry and the Future of Observability Part 1 Modern Platform Engineering: 9 Secrets of Generative Teams - Liz Fong-Jones Context Propagation makes OpenTelemetry awesome I've been developing a demo app (it has fewer features than the otel demo) to demonstrate how to build an app with OpenTelemetry, Grafana and Prometheus. It's primarily focused on a small app I can showcase in my talks. If you're interested take a look: / grafana-observability-demo Observability - Grafana Demo for Talks This is a simple demo showcasing how we can instrument our applications with OpenTelemetry, using Azure Monitoring + Grafana + Prometheus It's intended to be used as the demo of a specific talk about observability. Demo app instructions Read the instructions in src/README.md. Session Abstracts Observability with Azure Managed Grafana Nowadays, OpenTelemetry is used extensively to collect telemetry data from our applications, and serves as an industry standard. But we need a way to visualize this data in a clear way, and that is where Azure Managed Grafana comes in. In this session we'll go through the core concepts of observability and demonstrate how we can use Azure Managed Grafana, integrated with Prometheus Grafana Tempo and Loki to gather insights from our telemetry data We will cover topics such as the basics about logs, metrics and traces, manual instrumentation, OTLP, and others. We'll… View on GitHub Hopefully, some of these resources I've shared are useful to you πŸ˜„. I still have a ton to learn and explore, but I'm happy with the knowledge I've acquired so far. There are some specific standards + projects that I'll dive in and explore more, like: eBPF; OpenMetrics. OpenMetrics is something I'd like to spend some quality time reading about, but I know it's archived and reddit says the same. Just want to read and watch some talks about it to feed my curiosity πŸ˜ƒ. Last but not least, I want to follow the work that some industry leaders are doing like Charity Majors, specifically about Observability 2.0 πŸ˜„. I discovered this term in the Thouthworks tech radar, and the part "high-cardinality event data in a single data store" caught my interest. I'm still learning, researching, and listening to the opinions of industry leaders about this term to then develop my own opinions. Maybe I'll make a blog post about this in the future 😁.

Mar 30, 2025

I've wanted to write down what/who has helped me grow as a developer for quite some time. Well... here it is πŸ˜„. Here is a tweet where I shared talks that I enjoyed a ton, and helped me grow: // Detect dark theme var iframe = document.getElementById('tweet-1540783019862024194-83'); if (document.body.className.includes('dark-theme')) { iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1540783019862024194&theme=dark" } In this post, I'll share my retrospective about what has influenced me. I'll mention a few videos on that tweet that really molded who I am πŸ˜„ The person that taught me the most about communication and leadership was Paulo Neto. I'd had the privilege of participating in many group or 1-1 sessions with Paulo, with other colleagues from Create IT. You don't need to be the Tech Lead to be a leader on your team. Give feedback to your colleagues on what they did great, or what they can improve. This doesn't mean "always give specific instructions on how to get from point A to point B". The strategy we use to give feedback depends on the other person, but sometimes it's just better to ask questions, not give solutions. This challenges the other person to come up with a solution and think critically about the problem. I used to help by giving all the answers to the problems people asked me. By giving my opinion even if nobody asked for it. If I give away the solution right away, let's say to a junior dev, it means I just stole an opportunity for that person to grow. When you give feedback, the focus is on the other person's growth, not your own. I'm still getting better at being a human, but Paulo helped me a lot in being on the right path. This video really taught me what meant to learn. Re-learning is a part of the process! This completely changed how I look at certain topics. One more thing that is crucial, is to reserve time to learn! Saying "I don't have time to learn k8s" is the equivalent of saying "Learning k8s is not my priority right now". We have time for everything in this world, it's all a matter of priorities πŸ˜‚. I've sacrificed my learning/growing time to deliver user stories on the sprint, for several occasions. If you are saying yes to every request someone asks you, it usually ends up with you prioritizing those requests, and not your own time to learn k8s, for example. Sharing knowledge is a key differentiator for a software developer. Have you ever tried teaching something to your colleagues, then get follow-up questions? Are you able to answer all of them πŸ˜… ? Teaching helps you discover gaps in your knowledge, and it's something I'm still improving. To feel like an expert in a subject, you need to first explain it to someone that has no knowledge about it. If you try and you fail to get the other person to understand the subject, it means you have work to do. I've used many meetings with colleagues as a means to know if I deeply understand a subject like idempotency, microservices, BFF, CQRS, etc. Imagine you're onboarding a new teammate and you are the senior dev. Your capability to teach about the codebase, business domain, and other subjects is important. It can be the difference between having a new dev that is productive after one week, instead of one month. I've talked mostly in this post about my own growth... but that doesn't mean all I need to do is develop my own skills. the hardest challenge in this industry is making other people more productive! Not just making myself more productive and better at engineering πŸ˜…. Some people do this amazingly well, but I'm still growing in this regard πŸ˜„ Like Einstein said: If you can't explain it to a six year old, you don't understand it yourself. In retrospect, I follow just a few key people. As time passed, I focused on other interesting topics, instead of "simple tutorials" (the amount of content I consume didn't exactly decrease). Here is a list of the people I follow the most nowadays: ThePrimeTimeagen Derek Comartin Scott Hanselman Dave Farley One of the videos I loved the most from Scott was this one: What he shared really resonated with me. I felt powered up inside to keep learning and sharing, perhaps make more blog posts in Portuguese... but I never did that πŸ˜…. Also someone I have learned a ton is Emily Freeman. I absolutely loved this talk she made at GitHub Universe! Recently I shared another list of more front-end people I follow and recommend: David Pereira β€’ May 7 '23 I'd add some people to that list: Kent C. Dodds Dan Abramov Theo Guillermo Rauch They have either awesome blogs or videos that you can learn a lot from! I'd also recommend to follow and learn from Kelsey Hightower, for example this video. It's not particular about front end, but you can learn many valuable lessons from him :) I'm way more confident now, and all those people I mentioned made and shared content that helped me grow. If you're interested in AsyncAPI and CloudEvents, take a look at my post: Getting Started with CloudEvents and AsyncAPI David Pereira ・ Sep 16 '21 #eventdriven #cloudevents #asyncapi #architecture

Jun 26, 2023

Table of contents Introduction The problem The solution Alternative solutions to SEO meta tag rules Conclusion Additional Links We have a great feature available to us in Salesforce Commerce Cloud (SFCC) called SEO meta tag rules. This is a module inside of SEO in Business Manager (BM). only support for PDP/PLP pages made in page designer that support these meta tag rules. In this blog post we'll see how to support SEO meta tag rules for all pages made in page designer. Before going any further, I want to mention some disclaimers. At the time of writing this, not all pages in page designer support this. This could be added to SFCC and be directly supported without custom development. I posted this idea as a feature enhancement for Salesforce in IdeaExchange. With that said, let's take a step back and understand the problem. The SEO experts on a business operate mostly on the SEO meta tag rules BM module. If they need more granular level of SEO customization, most System Objects (e.g. Products, Content Assets, Categories) of SFCC support SEO fields like pageUrl, pageTitle, pageDescription. SEO experts can define rules that act as fallbacks, and then if some merchants don't define these fields for particular categories or pieces of content. You still have some meta tags being added to the page by these rules. Now, even though this feature supports many types of pages, like home page, product pages or product listing pages. It doesn't support all types of Page Designer (PD) pages. Page class, and check that it doesn't have the pageMetaTags field like the Content class does. Page Designer pages are very similar to Content Assets, in the sense that underneath, these pages are persisted as the same content objects on the SFCC's database. But there are still differences, the support for meta tag rules feature is one of them. Ultimately, these differences makes it harder for merchants or SEO experts that want to leverage the same functionality available on the rest of the site. Now that you have a better understanding about the problem, let's shift our focus into a solution. The whole premise of this solution is that it's supported by the SEO meta tag rules module of BM. In this module we have support for the following: Homepage Product pages Content Detail pages Content Listing pages The only one that fits well with a page designer page is Content Detail page. Meaning we'll create content assets as a way to support these SEO rules for Page Designer. Page.js you can get the meta tags for that page, through that content asset. Here is an example of the Page-Show extension: server.prepend("Show", function (req, res, next) { var PageMgr = require('dw/experience/PageMgr') var ContentModel = require('*/cartridge/models/content') var pageMetaHelper = require("*/cartridge/scripts/helpers/pageMetaHelper") var page = PageMgr.getPage(req.querystring.cid); if (page != null && page.isVisible()) { var pageContent = ContentMgr.getContent(page.ID + "-seo") if (pageContent) { var content = new ContentModel(pageContent, "content/content") pageMetaHelper.setPageMetaData(req.pageMetaData, content) pageMetaHelper.setPageMetaTags(req.pageMetaData, content) } } next() }) Now you don't need to create a content asset for every since page from PD. For example, if you business doesn't use the syntax ${Content.pageTitle} in your meta tag rules, or any expression regarding the object Content. Then in that case you could simply create one content asset for each folder the business wants to have. Folders are the way you can group multiple pages, and make all of them inherit the same meta tag rules. Once a folder is created, the business can use it in the SEO meta tag rules module inside BM. So far the solution revolves around the business creating manually folders, assigning them to pages and creating content assets for every page (in case they want to leverage page properties) or every folder. This is a critical step, since having all this manual work doesn't make sense for business people. As engineers we can do better and automate the creation of these content assets. We can develop two different pieces that play together: a job to ensure every page from Page Designer, has it's associated content asset and all the rest a new BM module to automate folder creation, specifically creating multiple folders Let's go through the job first, its responsible to update the content assets associated with each page. This means creating that content asset if it doesn't already exist, and then assign it to the same folders as the page. To implement this job you need: Get the list of all Page Designer pages Iterate through all pages For each page, create the content asset and assign the appropriate folders Here is a code snippet (in ES6) representing a possible implementation: const libraryGateway = require("*/cartridge/scripts/gateways/libraryGateway") const pagesList = getAllPageDesignerPages() pagesList.forEach(page => { const contentId = `${page.ID}-seo` const result = libraryGateway.createContentAsset({ id: contentId, pageTitle: page.pageTitle }) if (result.error) { throw new Error("Error creating content asset") } page.folders.forEach(folder => { const result = libraryGateway.assignContentAssetToFolder(contentId, folder.ID) }) }) function getAllPageDesignerPages() { const ContentSearchModel = require("dw/content/ContentSearchModel") const apiContentSearchModel = new ContentSearchModel() const libraryID = "someId" apiContentSearchModel.setRecursiveFolderSearch(true) apiContentSearchModel.setFilteredByFolder(false) apiContentSearchModel.setFolderID(libraryID) apiContentSearchModel.search() const contentSearchResultIterator = apiContentSearchModel.getContent() const count = Number(apiContentSearchModel.getCount()) const pages = [] if (contentSearchResultIterator && count > 0) { while (contentSearchResultIterator.hasNext()) { const contentResult = contentSearchResultIterator.next() if (contentResult?.page) { // transform some contentResult fields to other types... pages.push(contentResult) } } } return pages } In the implementation above, getting all pages from Page Designer is done through the ContentSearchModel API. Although this works, it's not ideal in my opinion since these pages are required to be searchable (a setting on all pages) and online. If they aren't, then they won't be on the Content index, which seems to be the only way to get all page designer pages on a given site. libraryGateway module. To implement this module we need to use OCAPI. We can use OCAPI Data APIs to create content assets/folders and assign content assets to folders. While researching I tried finding another way, but I didn't find anything easier. The Salesforce Commerce API (dw library accessible server-side) doesn't seem to have APIs for these operations. I didn't find any pipelets or jobs steps that do this either... perhaps by exporting the content library, then creating a custom job that reads that file, edits it with the new content objects, and finally runs a job step to import that edited file. Interacting with OCAPI is not an expensive development effort, so you can develop a custom cartridge for this. We won't go through the details about that cartridge, perhaps on a separate blog post :slight_smile: All the operations we want to do can be found on the Libraries resource from the Data API. To create a content asset we can use this endpoint, to assign it to a folder we can use this endpoint. One thing to keep in mind, creating a content asset is an idempotent operation. This means it creates the object if it doesn't already exist, but if it does it ignores the existing object and writes a new one on top. In practice, this means if someone edits these content assets (e.g. through BM, locking the resource and updating the description field), that modification will be lost. Now let's discuss the custom BM module to create folders. If business people want to create multiple filters in one go, instead of doing it through the BM UI and then going to Page Designer to assign pages to folders, they input the filter names in an input box and click a button. We can simply develop a web page that has this input box and a button (and some instructions on how to use it). This is possible by extending BM and building a custom cartridge, with this UI and the controller that executes the creation of folders. We won't go to much into detail about this custom cartridge, I've added additional links at the bottom to help you building this cartridge. In the case where the content object quotas are hit, we can consider building something entirely custom. What I mean is we would not use the SEO meta tag rules module from BM anymore. We would build our piece of software to handle this scenario - all page designer page types. Of course that means building software that does the same as Salesforce's built-in module of BM, considering: Storage to store these rules, meta tag definitions, and others An API that at least exposes a way to get meta tags for a given page, taking into account API design, SLA (important if you'll call this in a middleware of the Page.js controller), etc This is a discussion you must have with your business/client, explaining the trade-offs of each scenario. In my opinion, it's generally often better to reuse existing functionality or an off-the-shelf solution like a plugin cartridge. can't extend this module. So if we really needed to support this feature and we hit the API quotas of the SFCC platform, we would consider building a cost-effective solution outside SFCC, considering the need of a custom parser for if statements, context variables... again a discussion to be made with the business and architects. One important note about this solution is that pages would only inherit meta tags assigned to the default folder (primary folder). From my research, a content asset can only have one default folder, and that is the folder the meta tags come from. hierarchy (primary folder, then parent folders, up to root), but it's not the exact behavior I needed. In conclusion, you can develop a custom cartridge with this functionality, and support this for your business or clients. In the future, this might be supported out of the box by SFCC. The greatest challenges were: analyzing ways to extend the SEO meta tag rules module; an API to get all page designer pages and understanding the limitations of our solution. Let us know in the comments if this feature is something you'd like to have, or vote and comment on the IdeaExchange's post. I hope this has been helpful πŸ‘. Check out my other blog post on session management for SFCC. Here are some links to documentation and other resources, that you may find useful if you're interested in building this feature for your business: IdeaExchange's post How to get a list of pages of Page Designer using code? OCAPI Data Libraries resource Configuring the Business Manager Site

Nov 5, 2022

Lately we've been filled with cool stuff in the React community. In case you missed it, Reactathon happened at the beginning of May, and with it came a lot of interesting talks and discussions between people in the community. If you haven't seen the conference, you can take a look at this YT playlist for all sessions. So first of all, what is the state of React currently? With React 18, what was once called concurrent mode is now concurrent features. This changes the approach into an incremental adoption, so that you could use concurrent features in specific places of your React app. In this talk, Lee also announces Next.js new routing system which resembles Remix a lot. They want to take advantage of nested routes which is great! This allows us to provide a better user experience on pages that have one component that blocks rendering. Last but not least, there are new developments when it comes to server-side rendering, and new client-side rendering APIs. If you are unaware of this type of compute, Edge computing allows a better user experience, because it reduces the time you get a response with the content you want to visualize. The time is reduced because to process your request you don't need to "talk" to a distant server on the oasis. CDN providers like Cloudflare, are building new runtimes to allow you to run code closer to your customers – on the edge. Cloudflare workers for example, don't use Node.js or Deno under the hood, it's their own JS runtime. Of course, an effort is being done to standardize these runtimes. In this talk, Kent talks about how Remix improves the developer experience for edge computing. First they use the Web Fetch API, and depending on where you want to deploy your function. Remix then translates the request/response objects to the respective platform's API. They also support streaming in the edge, in order to send some content to the user quickly, and then send the rest. With that said, this is all in JS/TS or WASM land. At least I haven't seen a lot of support for other languages and runtimes (e.g. C#) on services that provide edge computing. With React 18 it's now possible to stream changes to the browser, with new APIs like Suspense that allows for asynchronous processing. Why is this cool? Because we don't want to block rendering with data fetching. When our component needs to fetch data before rendering what the user wants to see, we need to render a loading spinner... which ain't cool. How about we initiate fetches before we render. This way the requests are in parallel and don't block rendering. Using streaming server rendering fixes this, which is why it's so awesome! Ryan Florence goes more in detail how this is done in this talk: When to fetch: Remixing React Router. Bear in mind, this is just one way of rendering. Last year at React Conf 2021 there was an intro session about this topic as well: Streaming Server Rendering with Suspense. Another great session that talks about the different rendering patterns: Advanced Rendering Patterns: Lydia Hallie. It's an amazing session to help you visualize the impacts on performance, and what are the trade-offs of each pattern.

Jul 3, 2022

Table of contents Introduction CloudEvents AsyncAPI Conclusion Additional Links In the previous blog post we went over a case study for Azure Service Bus. In this article we’ll look at two specs, CloudEvents and AsyncAPI, that you can use to solve some problems of your event-driven architectures. At the moment, there are quite a few tools and products that have adopted CloudEvents or AsyncAPI. Knative Eventing is a tool that helps developers in a serverless context, Azure Event Grid natively supports CloudEvents. More recently, Jenkins added integration with CloudEvents with a new plugin. It allows users to configure Jenkins as a source and a sink for CloudEvents. There is also interesting integrations between Kubernetes and Azure Event Grid that are compliant with the CloudEvents v1.0 spec. Checkout the GitHub repository or this blog post and learn more about it. Postman has joined forces with AsyncAPI along with organizations such as Salesforce, Slack and Solace. Postman in particular is publishing public collections related to AsyncAPI. For example a list of companies adopting AsyncAPI, with links to those resources (GitHub repositories, websites, etc). I hope these projects have got you excited to learn more about these specs. Let’s dive into some of their details! The CloudEvents specification is under the CNCF Serverless working group since 2018. The spec's purpose is describing event data in a common way. This is useful in many scenarios, for example, routing events to the appropriate subscribers depending on the type of the event. Since applications can use a lot of different transports to send and receive events, the CloudEvents spec is protocol-agnostic so it defines protocol bindings in order for the metadata to be correctly mapped for HTTP, AMQP, Kafka, etc. There are many use cases in using the CloudEvents spec, but perhaps the main one would be interoperability. Imagine applications across clouds, being able to communicate in an event-driven architecture. Where there are producers of all sources, and consumers using all kinds of protocols (e.g. HTTP, AMQP, WebSockets). We can have middleware that connects these applications, adds E2E tracing and more with the use of CloudEvents. Of course we could connect the same applications without a common format, but it requires mapping between event formats (cloud providers use different schemas). Middleware would also need to parse the event data to get specific information. Another use case is SaaS (Software-as-a-service) that publishes events that clients are interested in to integrate with their own systems. For example, hooking into the checkout flow in a Shopify storefront to add extra checks. By leveraging CloudEvents these events can be consistent, opening the door for numerous integrations between 3rd party software. There are a few extensions worth mentioning, one of them is for distributed tracing. However, it seems there is some discussion around removing this extension from the spec (check this PR on GitHub). There are open issues on some SDKs to support it, and others have already made changes to remove it. The future isn't clear, but I'd argue it's interesting to follow this closely for any updates, since tracing events is very important in an event-driven architecture. The Partioning extension is another interesting extension, it defines a field to be handled by message brokers that can separate load via a partition key. This is used for example in the Kafka protocol binding that requires implementations to map the partitionKey attribute to the key of the Kafka message. In Kafka the concept of a partition is well known, so this maps out really well. Serverless computing has increased in popularity and use in the industry, especially for it's cost model. But many FaaS (Functions-as-a-service) providers have their own function interface. Which means developers can't write a function in JavaScript, and deploy them in two cloud providers without making changes. This specification improves portability between FaaS platforms, so that developers receive an event in the same format and can reuse libraries for handling the event. I’ll start with a description of what AsyncAPI is: a specification that describes and documents event-driven APIs in a machine-readable format. It's protocol-agnostic like CloudEvents, so it can be used for APIs that work over many protocols, including MQTT, WebSockets, and Kafka. The following is AsyncAPI's vision stated on their website: I find this vision to be very interesting, mainly because of the part: Any kind of APIs. At first, you might wonder if this means the AsyncAPI spec will define rules and more concepts for other types of APIs like GraphQL or OpenAPI. But this is not at all the case, the goal is to integrate with existing tools and specs! This is valuable for developers because usually enterprise architectures consist of a mix of technologies, each for it's appropriate use case. Developers nowadays don't just interact with RESTful APIs in a request/response model. There are different demands and considerations for the ever increasing devices users can use, the software we build needs to match these demands and still maintain manageable. Where we can evolve and create new applications that leverage the numerous APIs that exist internally or from a 3rd party. The spec version 2.1.0 defines a few concepts apart from the common Producer, Consumer and Message. A Channel can be seen as a topic/exchange or queue, an application can send messages to a channel and consumers can subscribe to it to receive them. The Operation object indicates if it's a publish or a subscribe operation and how an application can send or receive messages. A Binding (or "protocol binding") is a mechanism to define protocol-specific information or query parameters for the channel bindings. For example, for the AMQP protocol we can specify the channel is an exclusive queue like this: "bindings": { "amqp": { "is": "queue", "queue": { "exclusive": true } } } Each protocol has it's own JSON schema and we can have bindings for Messages, Servers, Channels, Operations and others. You can define components to reuse in multiple AsyncAPI documents and we can reference other AsncAPI documents. Let's say you have two publishers who publish the same message, but with different values in one of the message properties. We'd have two AsyncAPI documents specifying the publishers, referencing a 3rd document specifying the common message with it's properties. The $ref field is a string that can be the path to the other file, or a URL for an external file where the schema we want is defined. This reference object uses the same rules and format of JSON Reference, which opens the door for many possibilites (check the docs to know more). When we start to have a lot of apps that depend on each other’s schemas, we can take a look at some solutions to scale ou AsyncAPI documents. Perhaps we use Confluent's Schema Registry for our JSON schemas and setup a catalog of events in our organization. This empowers new developers seeking for ways to integrate with existing systems and event producers. We can also just store these components in a GitHub repository, and reference them in our AsyncAPI documents. There is already quite a few tools and the tooling ecosystem is increasing! I've recently seen a repository that enables the creation of Postman collections from an AsyncAPI spec. I've also seen architecture documents being generated from multiple AsyncAPI specs too, having a tool that can understand relations between applications and then output a diagram is pretty cool. One piece of tooling that is often used are generators that produce documentation and code. For example gRPC tools have this capability using the protocol buffer compiler. AsyncAPI generators can take an AsyncAPI document and generate client/server code or documentation in HTML and markdown. Currently, it depends on the template we use to generate server-side code, for example the Node.js WebSocket template generates both server and client code. This can be improved and extended overtime, especially because of the way the generator is designed, enabling extensibility so we can have templates for many other languages that support more protocols, etc. For example, there is only a NATS generator for .NET Core... but perhaps in the future there could be more protocols supported for .NET Core and examples built for Azure πŸ˜ƒ. There is a lot of exciting stuff happening in the event-driven architectures world πŸ˜„, we have only touched the surface in this post. In the CloudEvents space there are new specs being designed and worked on: Discovery; Subscription and Schema Registry APIs. Since AsyncAPI defines a document that you can use to describe your API, it'd be interesting to see how these correlate to each other, and using them together. I encourage you to join these communities and contribute to their open source projects πŸ˜„, CloudEvents and AsyncAPI, both specs are very community-driven. Collaboration between everyone is the way forward, with Hacktoberfest and AsyncAPI's Hackathon coming up, searching good first issues is a great way to start and to contribute πŸ‘! Let me know in the comments if you're using these specs and what are your thoughts on them. The next blog will be about a practical example for .NET Core, Azure and AMQP messaging using CloudEvents and AsyncAPI, so stay tuned! Here are some links to talks, docs and blog posts that you may find useful if you're interested to know more about CloudEvents and AsyncAPI: The Serverless and Event-Driven Future - Austen Collins, Serverless (Intermediate Skill Level) OpenFaaS supports CloudEvents The Future of API Specifications talk by Fran MΓ©ndez AsyncAPI 2.0: Enabling the Event-Driven World

Sep 16, 2021