Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
158419 stories
·
33 followers

🧠 MagenticBrain Is Now Supported in ElBruno.LocalLLMs

1 Share
MagenticBrain support hero

⚠ This blog post was created with the help of AI tools. Yes, I used a bit of magic from language models to organize my thoughts and automate the boring parts, but the geeky fun and the šŸ¤– in C# are 100% mine.

TL;DR


Why this model is important (and what it is designed for)

MagenticBrain is not just another general-purpose chat model. It is designed for agent orchestration: planning multi-step tasks, selecting tools, chaining tool calls across rounds, and deciding when to terminate with a final answer.

That design matters because many app scenarios need more than one prompt/one response:

  • file + web research workflows
  • iterative tool usage with state between turns
  • ā€œdo the task, then submit resultā€ orchestration patterns

In short, MagenticBrain is built for agentic execution loops, which is why it is a strong fit for .NET + LocalChatClient + MagenticUI experiences.


When Microsoft Research introduced MagenticLite, MagenticBrain, and Fara1.5, they framed a practical path for local agentic workflows:

For this repo, this post marks the concrete implementation milestone: MagenticBrain is now a first-class supported model in ElBruno.LocalLLMs.


Why this matters for MagenticUI scenarios

The target is a clean .NET workflow where orchestration and model inference stay in the same stack:

  1. UseĀ KnownModels.MagenticBrainĀ inĀ LocalChatClient.
  2. Keep tool-calling and multi-round logic in C#.
  3. Reuse the same model path for local multi-agent UX in MagenticUI-style applications.

This is exactly the scenario behind:

MagenticBrain architecture flow

Basic usage: MagenticBrain in C#

1. Install

dotnet add package ElBruno.LocalLLMs --version 0.20.4

2. Create a local MagenticBrain client

using ElBruno.LocalLLMs;
using Microsoft.Extensions.AI;
var options = new LocalLLMsOptions
{
Model = KnownModels.MagenticBrain,
EnsureModelDownloaded = true,
Temperature = 0.7f,
MaxSequenceLength = 32768
};
using var client = await LocalChatClient.CreateAsync(options);

3. Use it in an agentic loop with tools

var response = await client.GetResponseAsync(
[
new ChatMessage(ChatRole.System, "You are an agentic assistant. Use tools and call submit when done."),
new ChatMessage(ChatRole.User, "List project files and summarize README.")
],
new ChatOptions
{
Tools = tools
});
MagenticBrain agent round lifecycle

Repo samples you can run now

No extra sample project is required for this post: the existing MagenticBrain and MagenticUI samples already cover the runnable story.


Sample app screenshots (MagenticUIServer)

The following screenshots illustrate the sample app flow using the Magentic UI client and agent stream model:

MagenticUI sample connection and task submission
MagenticUI sample multi-round agent progress

You can run the sample from:


Relevant links

https://github.com/elbruno/ElBruno.MagenticUI

NuGet:Ā https://www.nuget.org/packages/ElBruno.LocalLLMs

Repository:Ā https://github.com/elbruno/ElBruno.LocalLLMs

Supported models reference:

https://github.com/elbruno/ElBruno.LocalLLMs/blob/main/docs/supported-models.md

Auto-download guide:

https://github.com/elbruno/ElBruno.LocalLLMs/blob/main/docs/auto-download.md

Official Microsoft announcement:

https://www.microsoft.com/en-us/research/blog/magenticlite-magenticbrain-fara1-5-an-agentic-experience-optimized-for-small-models/

Original MagenticBrain model:

https://huggingface.co/microsoft/MagenticBrain

Published ONNX package used by this repo:

https://huggingface.co/elbruno/MagenticBrain-onnx

Happy coding!

Greetings

El Bruno

More posts in my blog ElBruno.com.

More info in https://beacons.ai/elbruno




Read the whole story
alvinashcraft
18 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

How to promote a release from Development to Production With Argo CD and Octopus Deploy

1 Share

In vanilla Argo CD, "promoting to production" is really just editing a YAML file in a different folder and hoping you got it right. You bump an image tag in a production overlay, commit, and trust that what you just wrote matches what you verified in Development.

This is great until an auditor asks, "Who promoted this, and when?" or an incident traces back to a tag nobody meant to change.

Argo CD is excellent at keeping a cluster in sync with Git, but it has no concept of a release, i.e, no single, frozen artifact that moves from one environment to the next under policy.

In this guide, you will connect Argo CD to Octopus Deploy and turn promotion into a governed release, using the same immutable snapshot to move from Development to Production, gated by approval.

The Audit Stream and connection reuse the setup from our EKS connection walkthrough, so this article stays focused on promotion.

Why "promotion" is hard in vanilla Argo CD

Argo CD treats each Application as an independent unit. The dev install of your app and the production install are two separate Applications with no codified relationship between them. Nothing in Argo CD knows that "web in production" should receive exactly what "web in dev" was verified with.

Similarly, depending on your organization or team, promoting to an environment could mean a separate namespace or an entirely new cluster, both of which Octopus Deploy can handle.

That fragmented trail is slow and painful to reassemble at exactly the moments you need it most. Like when an auditor asks who promoted what and when, or when you are mid-incident trying to work out what changed.

Whereas, what you want is a single, frozen release that moves through environments under governance: verified once in Development, promoted unchanged to Production, with the who and when captured automatically.

That leaves two do-it-yourself options for promotion, and both are ad-hoc:

  • Hand-edit the image tag in each environment's overlay folder, commit, and let Argo sync. This is fast, but there is no record of intent, no gate, and nothing stopping a typo from shipping a different tag to Production than the one you tested.
  • Script a pull request per environment. This is more controlled, but now your promotion logic lives in CI YAML and shell, reinvented per team, drifting as the estate grows.

Whereas, what you want is a single, frozen release that moves through environments under governance: verified once in Development, promoted unchanged to Production, with the who and when captured automatically.

Prerequisites

This walkthrough builds on the cluster and Octopus connection from the EKS connection post. You do not need EKS specifically, but you do need these pieces in place before the promotion steps make sense:

  • An Octopus Deploy instance with the Argo CD integration (Octopus Cloud or self-hosted). This is where the project, lifecycle, and release live.
  • A Kubernetes cluster you can install into. A local kind cluster is enough. Because the Octopus gateway dials outbound, no ingress or public address is required.
  • Argo CD running in that cluster, connected to Octopus through the gateway. If you followed the EKS connection post, reuse that same cluster and its gateway connection. If you are starting fresh, the next section installs Argo CD and registers the gateway from scratch.
  • kubectl, helm, and the argocd CLI installed locally.
  • A Git repository for your manifests with Kustomize overlays per environment (the demo uses a public GitHub repo), plus a Git credential in Octopus that can push to it.

The architecture setup

For this demo, we're aiming for a single Kubernetes cluster with two namespaces that serve as environments, dev and production, each with its own Argo CD Application.

Octopus owns the release and promotion process, and Git remains the source of truth, while Argo CD applies manifests to the cluster.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/architecture.png" alt="How Octopus, Git, and Argo CD interact through commits." loading="lazy" }

::figcaption[Octopus commits the new image tag to the right overlay and triggers a sync through an in-cluster gateway. Argo CD pulls from Git and reconciles each namespace and Octopus never needs inbound access to your cluster.]

:::

The Octopus gateway is a small component you install in the cluster with Helm; it dials outbound to Octopus over gRPC, so nothing in your cluster needs a public address. That means this entire demo can run on a local kind cluster with no ingress.

For an in-depth look at the cluster and gateway connection, see the EKS connection post; here, we install Argo CD, register the gateway, and proceed to promotion.

Install Argo CD with a dedicated octopus account so the gateway has its own scoped identity rather than piggybacking on admin:

helm install argocd argo-cd \
 --repo https://argoproj.github.io/argo-helm \
  --create-namespace --namespace argocd --wait --timeout 10m \
 --values - << 'EOF'
configs:
  cm:
    accounts.octopus: apiKey
  rbac:
    policy.default: "role:readonly"
    policy.csv: |
      g, admin, role:admin
      p, octopus, applications, get, *, allow
      p, octopus, applications, sync, *, allow
      p, octopus, clusters, get, *, allow
      p, octopus, logs, get, */*, allow
EOF

With Argo CD running, register the instance in Octopus (Infrastructure, then Argo CD Instances, then Add Argo CD Instance), paste an auth token for the octopus account, and Octopus generates a Helm command for the gateway.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/register-argo-instance.png" alt="Register an Argo CD instance" loading="lazy" }

::figcaption[Registering the Argo CD instance. The service DNS name is the in-cluster address of the Argo CD API server.]

:::

Run the generated Helm command against your cluster, and Octopus confirms the connection: the gateway registers, connects to Octopus, and connects to Argo CD.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/install-gateway.png" alt="Install gateway" loading="lazy" }

::figcaption[The gateway bridges Octopus and Argo CD over an outbound connection. No inbound firewall rules required.]

:::

The gateway bridges Octopus and Argo CD over an outbound connection. No inbound firewall rules required.

Map the Applications with annotations

Octopus needs to know which Argo CD Applications belong to which project and environment. You declare that with two annotations on each Application manifest. No per-application configuration is needed in Octopus; the annotations handle the mapping.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-dev
  namespace: argocd
  annotations:
    argo.octopus.com/project: argo-web-promotion
    argo.octopus.com/environment: development
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/gitops-web-promotion
    targetRevision: main
    path: overlays/dev
  destination:
    server: https://kubernetes.default.svc
    namespace: dev
  syncPolicy:
    automated: { prune: true, selfHeal: true }
    syncOptions: [ CreateNamespace=true ]

The argo.octopus.com/project annotation ties the Application to the Octopus project, and argo.octopus.com/environment ties it to an Octopus environment. The production Application is identical except name: web-production, argo.octopus.com/environment: production, path: overlays/production, and namespace: production.

When Octopus deploys argo-web-promotion to Development, it now knows web-dev is the Application to update; when it deploys to Production, it updates web-production.

Both overlays are simple Kustomize folders that set the image tag. This is the field Octopus will rewrite:

# overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
resources:
 - ../../base
images:
 - name: nginx
    newTag: "1.27.0"

Building the Octopus project with a Dev to Production lifecycle

Create an Octopus project and give it a lifecycle with two phases, Development and Production. The lifecycle is what makes promotion ordered, which simply means a release must pass through Development before it can reach Production.

Then add the built-in Update Argo CD Application Image Tags step to the deployment process. For each Application matched by annotation, this step retrieves the Git location from the Application, updates the image tag in the manifests, commits the change, and triggers Argo CD to sync. Add a container image reference (the nginx image, from a Docker Hub feed) so the release knows which image to update and what version to pin.

To make the governance visible, add one more step before it: a Manual intervention step scoped to the Production environment only. That is your approval gate. It runs when promoting to Production and is skipped for Development, so it stays fast while Production stays governed.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/argo-web-promotion.png" alt="Argo web promotion" loading="lazy" }

::figcaption[Two steps, one governed process. The approval runs only for Production; the image-tag update runs for any environment.]

:::

Create a release and deploy to Development

Create a release in Octopus and select the image version to promote, for example nginx:1.27.2 (a bump from the 1.27.0 currently in the overlays). This release is a frozen snapshot of the process, variables, and package versions. Once created, it is immutable: the version that goes to Production later is the exact version you are about to verify in Development, not whatever happens to sit at Git HEAD.

Deploy the release to Development. Octopus commits the new tag to the dev overlay, and Argo CD syncs the dev namespace:

Credential 'gitops-web-promotion' will be used to access the repository
Committing directly to branch for changes in this environment
Cloning repository https://github.com/your-org/gitops-web-promotion

Within seconds, the dev Application is synced and Healthy on the new tag, while Production is untouched:

$ kubectl get deploy web -n dev -o jsonpath='{..image}'
nginx:1.27.2
$ kubectl get deploy web -n production -o jsonpath='{..image}'
nginx:1.27.0

That contrast is the whole point: the release moved dev to 1.27.2, and Production still runs 1.27.0 because nothing has promoted it there yet.

Promote the same release to Production

Now promote the same release to Production. Because the process has a Production-scoped approval step, the deployment pauses and waits for a human before it touches anything.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/deploy-to-production.png" alt="Promoting the release to Production with an approval step." loading="lazy" }

:::

Production promotion stops at the approval gate; the image update and sync below it are queued, not run.

Approve it, and the same flow runs against the production overlay: Octopus commits the tag to overlays/production, and Argo CD syncs the production namespace. Production now gets exactly what was verified in dev, not a freshly hand-edited value.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/promotion-result.png" alt="Promotion result" loading="lazy" }

::figcaption[Promotion complete. The same release 1.27.2 that ran in Development is now live in Production.]

:::

The project dashboard shows the end state at a glance: one release, both environments, both healthy, with the live status pulled from Argo CD.

:::figure

:img{ src="/blog/img/promote-release-with-argo-cd-and-octopus/dashboard.png" alt="Project dashboard" loading="lazy" }

::figcaption[Development at 9:06 PM, Production at 9:43 PM after approval. Same release, one predictable shape.]

:::

The governance you got for free

Taking a step back, there are a few things this approach has saved you from:

  • An immutable release snapshot. Release 1.27.2 pinned the exact image version. Production could only ever receive what dev verified.

  • A Git commit per environment. Each promotion is a commit in your history, attributable and reversible:

07d62d8  Octopus Deploy promoted image 1.27.2   (production overlay)
28e2ace  Octopus Deploy promoted image 1.27.2   (dev overlay)
dfdadc8  Initial GitOps repo
  • An approval record. Production promotion required a named human to take responsibility and proceed, captured in the deployment history.

  • One view of what is running where. The project dashboard shows every environment and the release it holds, with live health from Argo CD, and you can click into any deployment to see who promoted it and when. That single pane matters more as you scale because your Argo CD Applications might be spread across many instances in different clusters, regions, or accounts, and Octopus gives you one place to see and govern all of them instead of tab-hopping between Argo CD UIs.

None of this is captured by default in the hand-edited-overlay approach. Because the Octopus release is a standard, predictable object, the same governance and policy apply no matter what sits underneath

This ties into the core Platform Hub idea: a single deployment shape and consistent governance across every stack you run.

Going from overlay edits to audited releases

Promotion should not be a YAML edit you hope you got right. With Argo CD connected to Octopus, it becomes a release you can govern.

Argo CD keeps doing what it does best: reconciling Git with your cluster, while Octopus adds a release model and an audit trail to that flow.

The bigger idea here is Platform Hub, which offers you one place to see what is running where, and the same governance and audit across every environment, cluster, and Argo CD instance you run, not just the one in this walkthrough.

If you promote Argo CD deployments by hand today, that is the gap it closes. See how Platform Hub brings your GitOps deployments under one governed roof, read Manage releases and rollbacks with Argo CD for the release mechanics, and start for free!

Read the whole story
alvinashcraft
38 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

How to Provision an Azure SQL Database

1 Share

Aside from spinning up a SQL Server instance container, the free Azure SQL Database is another great tool for learning SQL. You can even use it for low-traffic or lightweight app. See the documentations for the limits. I will not be responsible for your usage.

That said, let’s provision the database.

Provision an Azure SQL Database

Go to you Azure Portal and search for Azure SQL Database

On the upper left-hand of the UI, click on Create and select SQL database (Free offer).

Configuring an Azure SQL Database is pretty much intutive. For the Server option, use an existing SQL Database Server or create a new one.

Click Review + create to finish the setup.

Connect from VS Code on a MacBook

Go to your Resource Group and find your Azure SQL Database. Or, you can simply search for Azure SQL Database in the search bar again and that will take you to your databases.

Copy the Server name.

Now, open your VS Code (install the mssql extension if you haven’t already). Why VS Code? That’s because Mirosoft will never port SSMS to macOS. That’s why.

Create new connection. Look for the plug icon with the ā€˜+’ sign next to it.

For the Input type, Browse Azure wouldn’t work for me even if I already took care of the networking setting. Let me know in the comment if you made it work. Using Parameters worked for me.

Paste the Server name. Don’t forget to tick the Trust server certificate. Use SQL login and input the sa user and password that you set when you provisioned your SQL Server.

That should be it. Your Azure SQL Database is now ready to use.

The post How to Provision an Azure SQL Database first appeared on SQL, Code, Coffee, Etc..

The post How to Provision an Azure SQL Database appeared first on SQLServerCentral.

Read the whole story
alvinashcraft
50 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Learn T-SQL With Erik: Variables and Date Math

1 Share

Learn T-SQL With Erik: Variables and Date Math


Chapters

Full Transcript

Alright, it’s the last one of the week, you can all breathe a sigh of relief, till next week, till hell begins again, unremitted, anyway, don’t let me rub off on you, in this video we’re going to learn some more about T-SQL, stuff around variables and date math, so that’ll be fun right, everyone likes fun, alright, down in the video description, you will find potentially one of the more important links that you will ever click on in your life, and that is the link to purchase this training for $100 off, there are also other links in there, which I think are equally valuable, depending on your goals and needs in life, where you can hire me for consulting and become a supporting member of this very YouTube channel, you can also ask me office hours questions, which I will answer every Tuesday, faithfully.

I used to answer them faithfully every Monday, but then I cheated on Monday with Tuesday, and now, I don’t know, I’m stuck with Tuesday, Monday dumped me, I don’t know, the whole sordid thing, might have to, I don’t know, I don’t know what to do here, it’s a sordid love triangle, anyway, and if you perhaps want to do, just do me a solid in life, you can of course like, subscribe, and tell a friend, in the video description there’s also links if you want to…

Have free SQL Server performance monitoring, you can do that, from me, it’s my gift to you, just for existing, and using SQL Server, that’s all, that’s it, the only bar for entry, totally free, open source, no weird sign up, phone home stuff, I don’t want to know more about you, or anything like that, just a bunch of T-SQL collectors, running on a schedule, collecting all the important things that you would ever want to know about your SQL Servers, wait stats, blocking, deadlocks…

Bad queries, CPU, memory, disk, you name it, it’s all in there, doesn’t get better than that, especially for that price, alright, anyway, let’s talk about this stuff here, let’s do the damn thing, so, one thing that I want to talk about, and this is a good start to things, is a pattern that I see in a lot of stored procedures, that I wish that I didn’t, and that is…

We have, for simplicity’s sake, we have one parameter in here, and it is nullable, right, by default, it is nullable, so you don’t have to pass anything in here, you’re not going to get an error, it’s like, SQL Server expects a value here, right, so, what a lot of people will end up doing, is, if the date comes in as null, they have a safeguard on it, and the safeguard, I mean, it couldn’t be anything, but, we’re going to use 2013-1201 for our safeguard, and we’re going to look at the side effects and repercussions of such a bit of code.

So we’ve got query plans turned on, and if we run this, and let’s say that a null gets passed in the first time around, and this is going to run, and run, and run, run so far away, I don’t know, something like that, and we look at the execution plan, we didn’t do too well, right?

SQL Server… SQL Server guessed that we were going to get one row, we got 1, 5, 2, 6, 9, 9, 7, we got 1.5 million rows back, we did 1.5 million key lookups, and we didn’t get a very, I mean, this isn’t the worst of it, because, like, we only go about 600 milliseconds in here, so that’s not, like, terrible, but, you know, our sort didn’t get enough memory, ba-ba-ba-ba-ba, we’re all sad, we’re all having a bad time.

And what’s funny… is that if we go into this portion of the query plan, this is in the properties tab, because we got an actual execution plan, we can see the compile and the runtime value here, and notice that this query was compiled with a cardinality estimate for null, however, it was run with a cardinality, well, not with a cardinality, it was run with the requirement to return everything.

Everything greater than 2013-1201, which is quite a discrepancy in rows, isn’t it? Sure is. Sure is.

So just replacing or overwriting a null with a value in the context of, well, in this context, it is a formal parameter, does not really get you what you want, I don’t think, because you still compiled with a cardinality estimate for null.

That was what your plan was compiled with, despite what it was run with. And if we look at the histogram for the, what do you call it, that we created, the index, we have this one thing here, and we’re basically getting this estimate for the, ah, PowerShell, go away.

I don’t know why. There’s too many button combinations these days. There’s too many hotkeys. It’s getting too damn hot. We basically got this estimate, all right? So that’s not a very good time for us, all right? We’re not enjoying ourselves.

We are not having a good time. Another problem that I see quite often is a little bit more like this, where someone will have, this is an example of someone passing in an integer value that gets added to a time.

So what that usually ends up looking like is two declines. The first one is, you know, we start with the integer value, which is the date of the time when the date of the end date is this one, right?

And the second one is, the second one is the start date, which is the time when the end date is this one. And the third one is the time when the end date is this one, right? And, gee, I hope I didn’t hit a weird button there. That jumped in a strange way that frightened me. I was like, oh, what did you do?

But if we run this store procedure with the local variables in place, and we run these three representative executions of the stored procedure, note the 1, 10, and 5 here, and we will get the same bad cardinality estimate for all of them, right? And this feels like a parameter sniffing thing, and like normally it would be a parameter sniffing thing if there were a parameter, but there’s no parameter within the perimeter, there is just a local variable, so we’re getting the density vector guess, we are not getting a compiled parameter, a sniffed parameter value guess, and that becomes especially incorrect, well I mean they’re all incorrect, right? We got like SQL Server is guessing 8, 6, 9, 7, 0, 8, 0 for all of these, even though we get back far less, so the estimated and actual rows for this are way off because we used these declared variables and we added some time to them.

So, let’s skip over, that doesn’t actually run. What you’re much better off doing, for these cases, is just using the expression itself in the WHERE clause, this is identical to what we had those local, the part that we had those local variables playing in the earlier bit of code, but now when we use the parameters here, SQL Server gets not only a stable guess, but a guess that is, ah, wait a minute, I did that wrong.

What I should have noted, before running those, was this being the old version, and this being the new version, right? So this is the one where we have the local variables, this is the one where we have the expressions embedded in the WHERE clause, and if we come back and look, this one gets the same bad treatment, with the bad cardinality estimate, but this one gets a much more appropriate cardinality estimate because we did not use local variables.

variables we put the expression directly in our where clause. So that is what we want to do and that is what you want to do when you are writing your store procedures. All right it’s all for me. It’s Thursday. It’s the last video of the week which means it’s a long weekend for everyone and I will see you next Tuesday with Office Hours. All right thank you for watching.

Going Further


If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.

The post Learn T-SQL With Erik: Variables and Date Math appeared first on Darling Data.

Read the whole story
alvinashcraft
56 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

The Economic Benefit of Refactoring

1 Share

Giles Edwards-Alexander does an experiment to see if decomposing a large function helps reduce token costs, suggesting that is may now be possible to measure the economic benefit of refactoring

more…

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

How we set up our cloud agent environment

1 Share
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories