<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ai</title>
    <description>The latest articles tagged 'ai' on DEV Community.</description>
    <link>https://dev.to/t/ai</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tag/ai"/>
    <language>en</language>
    <item>
      <title>Building an AI Video Workflow with MiniMax H3: Text-to-Video and Image-to-Video</title>
      <dc:creator>Jaysean Brambila</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:39:50 +0000</pubDate>
      <link>https://dev.to/jaysean_brambila_1f12d6cc/building-an-ai-video-workflow-with-minimax-h3-text-to-video-and-image-to-video-221c</link>
      <guid>https://dev.to/jaysean_brambila_1f12d6cc/building-an-ai-video-workflow-with-minimax-h3-text-to-video-and-image-to-video-221c</guid>
      <description>&lt;p&gt;AI video generation has become much easier to experiment with, but building a useful workflow still involves more than simply entering a prompt.&lt;/p&gt;

&lt;p&gt;I've recently been exploring &lt;strong&gt;MiniMax H3&lt;/strong&gt; for both text-to-video and image-to-video generation. In this post, I'll share a simple workflow for getting more consistent results.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with a clear visual goal
&lt;/h2&gt;

&lt;p&gt;Before writing a prompt, define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subject&lt;/li&gt;
&lt;li&gt;Environment&lt;/li&gt;
&lt;li&gt;Camera movement&lt;/li&gt;
&lt;li&gt;Lighting&lt;/li&gt;
&lt;li&gt;Visual style&lt;/li&gt;
&lt;li&gt;Desired motion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A woman walking in a city&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try something more structured:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A woman in a black coat walking through a rainy Tokyo street at night, cinematic lighting, reflections on wet pavement, slow tracking shot, shallow depth of field.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal is not necessarily to make the prompt longer. It is to make every part of the prompt useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Text-to-video works best with controlled motion
&lt;/h2&gt;

&lt;p&gt;For text-to-video generation, I usually separate the prompt into three parts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scene + Motion + Camera&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A futuristic train moving through a neon city, rain falling across the windows, camera slowly tracking alongside the train.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This makes it easier for the model to understand what should move and how the camera should behave.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Image-to-video needs a different approach
&lt;/h2&gt;

&lt;p&gt;With image-to-video, the source image already defines most of the visual information.&lt;/p&gt;

&lt;p&gt;The prompt should focus more on motion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Character movement&lt;/li&gt;
&lt;li&gt;Camera movement&lt;/li&gt;
&lt;li&gt;Environmental effects&lt;/li&gt;
&lt;li&gt;Changes over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The camera slowly pushes forward while the character turns toward the window. Curtains move gently in the wind and sunlight shifts across the room.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is often more reliable than describing the entire image again.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Keep iterations small
&lt;/h2&gt;

&lt;p&gt;One mistake I made early on was changing too many things between generations.&lt;/p&gt;

&lt;p&gt;A better workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate a basic version&lt;/li&gt;
&lt;li&gt;Identify the biggest problem&lt;/li&gt;
&lt;li&gt;Change one or two prompt elements&lt;/li&gt;
&lt;li&gt;Generate again&lt;/li&gt;
&lt;li&gt;Compare the result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Small iterations make it much easier to understand what is actually improving the output.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. A simple browser-based workflow
&lt;/h2&gt;

&lt;p&gt;For anyone experimenting with this process, I've been using &lt;a href="https://minimax3.org" rel="noopener noreferrer"&gt;MiniMax H3&lt;/a&gt; to test text-to-video and image-to-video workflows in the browser.&lt;/p&gt;

&lt;p&gt;The main thing I'm interested in is reducing the number of steps between an idea, a reference image, and a usable video result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example prompt structure
&lt;/h2&gt;

&lt;p&gt;A reusable structure I've found useful is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Subject + Action + Environment + Camera + Lighting + Style&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A vintage sports car driving along a coastal highway at sunset, ocean visible in the background, low-angle tracking shot, warm cinematic lighting, realistic film look.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For image-to-video:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Subject Motion + Environmental Motion + Camera Motion&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The character slowly raises her head, hair moving gently in the wind, clouds drifting in the background, camera slowly pushing forward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;AI video generation is improving quickly, but prompt structure and iteration still make a noticeable difference.&lt;/p&gt;

&lt;p&gt;I'm especially interested in how these tools can become easier for creators who don't want to think about the underlying model or technical workflow.&lt;/p&gt;

&lt;p&gt;If you're experimenting with AI video generation too, I'd be interested to hear what prompt structures or workflows have worked best for you.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fns07fshx925urnl9nj9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fns07fshx925urnl9nj9o.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Your container is shipping software you've never heard of</title>
      <dc:creator>Mr Recruiter</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:37:21 +0000</pubDate>
      <link>https://dev.to/nodevguy/your-container-is-shipping-software-youve-never-heard-of-38jp</link>
      <guid>https://dev.to/nodevguy/your-container-is-shipping-software-youve-never-heard-of-38jp</guid>
      <description>&lt;p&gt;Here's an uncomfortable fact about the container you're about to deploy. You wrote a small fraction of what's inside it. The rest, the base image, the OS packages, the dependencies, the dependencies of your dependencies, came from somewhere else, and most teams ship it all to production without ever really looking at what's in there. Container image security is mostly about closing that gap, knowing and controlling what's actually in the box you're running. Let me break down where it goes wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your base image is a decision, not a default&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Almost every container starts FROM something, and that base image sets the tone for everything. The common instinct is to grab a big, familiar, full-featured base because it's convenient and everything you might need is already there. That convenience is a security cost. A large base image comes with a huge amount of software you're not using, and every one of those unused packages is potential attack surface, another thing that could have a vulnerability, another thing an attacker could use if they get in.&lt;/p&gt;

&lt;p&gt;The move is to start minimal. Use small, purpose-built base images that contain close to only what your application actually needs. Less software in the image means less that can be vulnerable, less that can be exploited, and a smaller thing to reason about. Minimal base images aren't just smaller and faster, they're meaningfully more secure purely by having less in them to go wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You inherit every vulnerability in everything you include&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you build an image, you inherit the security state of everything in it, the base OS, its packages, your language dependencies, and all of their transitive dependencies. And software has vulnerabilities discovered constantly, so an image that was clean when you built it accumulates known vulnerabilities over time as new ones are found in the things it contains. The image didn't change, the world's knowledge of its flaws did.&lt;/p&gt;

&lt;p&gt;This is why image scanning matters, and why it's not a one-time thing. A scanner checks your image against databases of known vulnerabilities and tells you what's in there that's now known to be exploitable. You want this running automatically as part of your build, so a new image gets checked before it ships, and ideally you also re-scan images already in production, because something clean last month may have known holes today. Scanning isn't optional hygiene, it's how you find out what you're actually shipping before an attacker does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't run as root, because why hand over the keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, containers often run their processes as root, the all-powerful user. This is convenient and dangerous. If an attacker manages to break out of or compromise your application inside a container running as root, they've got far more power to cause damage than they would against a process running as a limited user. It's the difference between an intruder finding a locked interior and an intruder handed the master key on the way in.&lt;/p&gt;

&lt;p&gt;So run your containers as a non-root user with only the permissions the app needs. It's a small change in your image definition and it meaningfully limits what a compromise can do. This is least privilege again, the same principle everywhere, don't give a process more power than its job requires, so that a compromise of it stays small.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where your images come from matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pulling base images and tools from public registries is normal and fine, but it's worth being deliberate about it, because you're trusting whoever published them. Use official and trusted sources rather than random unmaintained images, because a malicious or abandoned base image is a genuine supply-chain risk, you'd be building on top of someone else's problem, or someone else's trap. Prefer well-maintained, official images, and be suspicious of pulling arbitrary images from unknown publishers into your build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pin what you build on, so it doesn't shift under you&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A subtle one: if your build grabs "the latest" of things, your image can change unpredictably between builds, and you can't be sure what you're actually shipping, or reproduce a build to investigate a problem. Pinning to specific versions makes your builds predictable and makes it possible to know and control exactly what's in your image. It also means a bad new version of something upstream doesn't silently flow into your next build. Predictability is a security property here, because you can't secure what you can't pin down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't bake secrets into images&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One specific trap worth calling out: never build secrets into your container images. A key or password baked into an image is sitting in that image wherever it goes, in every registry it's pushed to, readable by anyone who can pull it, and present in the image's layers even if a later layer "removes" it. Secrets get provided to containers at runtime, from a proper secrets system, not baked in at build time. An image should be safe to store and share, and a baked-in secret makes it the opposite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mental model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A container image is a bundle of software, most of which you didn't write, shipped as one unit. Security is about knowing and minimizing what's in it. Start from minimal, trusted base images. Scan for known vulnerabilities automatically, and re-scan, because the vulnerabilities in a static image grow over time. Run as non-root so a compromise stays contained. Pull from trusted sources and pin versions so your builds are predictable and you know what you're running. And never bake secrets in. The theme is the same throughout: you're responsible for everything in the box, so put less in it, know what's there, and give it as little power as it needs to do its job.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Epigenetic Testing Protocol: Essential ML Accuracy</title>
      <dc:creator>Vladimir Lialine</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:36:15 +0000</pubDate>
      <link>https://dev.to/vladimir_lialine_b2e67374/epigenetic-testing-protocol-essential-ml-accuracy-2ce0</link>
      <guid>https://dev.to/vladimir_lialine_b2e67374/epigenetic-testing-protocol-essential-ml-accuracy-2ce0</guid>
      <description>&lt;p&gt;A well-designed &lt;strong&gt;epigenetic testing protocol&lt;/strong&gt; can estimate how quickly a person is aging, but laboratory consistency alone does not guarantee a reliable result. Biological signals are noisy, populations differ, and conventional statistical clocks may miss complex relationships among methylation sites. Machine learning improves accuracy by identifying those relationships while controlling for technical variation, demographic bias, and overfitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building an Accurate Epigenetic Testing Protocol
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Epigenetic testing&lt;/strong&gt; measures chemical modifications that regulate gene activity without changing the underlying DNA sequence. Most aging tests examine methyl groups attached to CpG sites—DNA regions where cytosine is followed by guanine.&lt;/p&gt;

&lt;p&gt;The resulting &lt;strong&gt;DNA methylation analysis&lt;/strong&gt; produces values representing the proportion of methylated DNA at thousands of sites. A model then converts this high-dimensional profile into an age-related estimate.&lt;/p&gt;

&lt;p&gt;A reliable workflow generally includes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Standardized sample collection:&lt;/strong&gt; Use consistent collection materials, storage temperatures, and processing timelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laboratory quality control:&lt;/strong&gt; Remove samples with weak signal intensity, contamination, or low probe coverage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data normalization:&lt;/strong&gt; Correct systematic differences between plates, reagent batches, and processing dates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature selection:&lt;/strong&gt; Retain CpG sites that provide reproducible age-related information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent validation:&lt;/strong&gt; Evaluate the final model on people who were not included during training.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These controls matter because a highly predictive model can still be clinically misleading if it learns laboratory artifacts rather than biological patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Machine Learning Improves Biological Age Measurement
&lt;/h2&gt;

&lt;p&gt;Traditional age estimators often rely on a fixed linear relationship between selected methylation sites and chronological age. Machine learning can model nonlinear effects, interactions, and coordinated changes across larger CpG panels.&lt;/p&gt;

&lt;p&gt;For example, regularized models reduce the influence of unstable variables, while tree-based and neural approaches can detect conditional relationships. A methylation site may have little predictive value alone but become informative when evaluated alongside immune-cell composition, smoking exposure, or other sites.&lt;/p&gt;

&lt;p&gt;Machine learning improves &lt;strong&gt;biological age measurement&lt;/strong&gt; through several mechanisms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filtering redundant or low-quality methylation features&lt;/li&gt;
&lt;li&gt;Correcting for estimated blood-cell composition&lt;/li&gt;
&lt;li&gt;Detecting nonlinear aging trajectories&lt;/li&gt;
&lt;li&gt;Calibrating predictions across age groups&lt;/li&gt;
&lt;li&gt;Quantifying uncertainty around each estimate&lt;/li&gt;
&lt;li&gt;Monitoring model drift as new samples are processed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Accuracy Requires More Than a Low Error Score
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mean absolute error (MAE)&lt;/strong&gt; is the average difference between a predicted value and its reference value. Although useful, MAE should not be the only performance metric.&lt;/p&gt;

&lt;p&gt;A model should also be tested for calibration, repeatability, subgroup performance, and sensitivity to batch effects. Cross-validation must be performed at the participant level so samples from the same person cannot appear in both training and validation sets. This prevents &lt;strong&gt;data leakage&lt;/strong&gt;, where information from the test set unintentionally helps train the model.&lt;/p&gt;

&lt;p&gt;Researchers must also define what “biological age” means. Chronological age is an observable label, but healthspan, organ function, and mortality risk are different targets. A clock trained only to predict calendar age may not measure the effects of disease or lifestyle interventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Methylation Data to Actionable Results
&lt;/h2&gt;

&lt;p&gt;An operational epigenetic testing protocol should preserve traceability from the original sample to the final report. Record assay version, processing batch, normalization method, model version, confidence interval, and quality-control exclusions.&lt;/p&gt;

&lt;p&gt;Platforms such as &lt;a href="https://dlamarck.com" rel="noopener noreferrer"&gt;Lamarck biological age analytics&lt;/a&gt; can support the transition from complex molecular data to understandable aging insights. Related health-data ecosystems, including &lt;a href="https://honeypotz.net" rel="noopener noreferrer"&gt;HONEYPOTZ INC health technology resources&lt;/a&gt; and &lt;a href="https://deepbody.me" rel="noopener noreferrer"&gt;DEEPBODY INC body-data tools&lt;/a&gt;, illustrate how biomarker information can be connected with broader wellness workflows.&lt;/p&gt;

&lt;p&gt;However, an age estimate should not be treated as a diagnosis. Results are most useful when interpreted longitudinally under similar collection conditions. Repeated measurements can reveal direction and rate of change more reliably than a single isolated score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Epigenetic Testing FAQ and Key Takeaways
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can machine learning eliminate measurement error?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No. It can reduce predictable error, but it cannot rescue poor samples, inconsistent laboratory procedures, or unrepresentative training data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is independent validation essential?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Testing on an external population shows whether the model generalizes beyond its original laboratory, batch, or demographic group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What makes an epigenetic result trustworthy?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Look for transparent quality controls, documented model versions, confidence ranges, subgroup validation, and clear disclosure of the prediction target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaway:&lt;/strong&gt; Machine learning strengthens epigenetic age estimates when it is paired with rigorous laboratory controls, leakage-free validation, and responsible interpretation.&lt;/p&gt;

&lt;p&gt;Turn DNA methylation data into clearer, more defensible aging insights. Explore the &lt;a href="https://dlamarck.com" rel="noopener noreferrer"&gt;Lamarck epigenetic intelligence platform&lt;/a&gt; and start building a more precise biological age workflow today.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;📱 Stay Connected — SMS Alerts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Want exclusive offers, early access to Private EDGE OS, and AI longevity insights delivered straight to your phone?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://honeypotz.net/sms-landing?incentive=EDGE10" rel="noopener noreferrer"&gt;Text EDGE10 to claim $10 off →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No spam. Reply STOP to unsubscribe anytime.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>technology</category>
    </item>
    <item>
      <title>Secrets management: your .env file was never the plan</title>
      <dc:creator>Mr Recruiter</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:35:50 +0000</pubDate>
      <link>https://dev.to/nodevguy/secrets-management-your-env-file-was-never-the-plan-2kjm</link>
      <guid>https://dev.to/nodevguy/secrets-management-your-env-file-was-never-the-plan-2kjm</guid>
      <description>&lt;p&gt;Every project starts the same way. You need an API key, so you drop it in a .env file, add .env to .gitignore, and move on. Totally fine for day one. The problem is that day one becomes month eighteen, the .env approach quietly becomes your entire secrets strategy, and now you've got credentials scattered across developer laptops, CI configs, and server environment variables with no idea who has what or when anything last changed. Nobody decided to run secrets this way. It just accumulated. Let me walk through what actually goes wrong and what to do instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The .env file's real problems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The .env file isn't evil, it's just not a strategy, and here's where it breaks down as you grow. It lives on disk in plaintext, so anyone with access to that machine can read every secret. It gets copied around, to laptops, to servers, pasted into Slack when someone's setting up, and every copy is another place a secret can leak. There's no access control, it's all-or-nothing, if you can read the file you have everything. There's no audit trail, no way to know who accessed a secret or when. And there's no rotation story, changing a secret means hunting down every copy and updating it by hand, which means in practice nobody rotates anything, ever.&lt;/p&gt;

&lt;p&gt;None of that matters with one developer and three secrets. All of it matters with a team and fifty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mistake that dwarfs all the others: secrets in git&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before anything else, the single most common and most damaging secrets mistake is committing them to your repository. It happens constantly, a key hardcoded in a file, a .env accidentally committed, a config with a password pushed up. And here's the part people underestimate: once a secret is in git history, adding it to .gitignore later does nothing, because it's already in the history, permanently, and anyone who can see the repo, or ever cloned it, has it.&lt;/p&gt;

&lt;p&gt;Git remembers everything. A secret committed once and "removed" in the next commit is still sitting right there in the history. So the rule is absolute: secrets never go in git, not in code, not in config, not "temporarily." Use a scanning tool that catches secrets before they're committed, because humans miss them and the cost of a miss is high. And if one does get committed, treat it as compromised and rotate it immediately, don't just delete the line, because deleting the line doesn't un-leak it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What a real secrets setup looks like&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core idea of proper secrets management is simple: store secrets in a dedicated system built for it, not scattered in files, and have your applications fetch them at runtime rather than having them sitting around baked into configs.&lt;/p&gt;

&lt;p&gt;A dedicated secrets manager gives you the things .env can't. Secrets stored encrypted, not plaintext on disk. Real access control, so you can say this service can read these specific secrets and nothing more. An audit trail, so you know who or what accessed what and when. And a rotation story, so changing a secret is a managed operation, not a scavenger hunt. Your app authenticates to the secrets manager and pulls what it needs when it starts or when it needs it, so the secret lives in memory at runtime rather than persisting in a file someone can grab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Least privilege applies to secrets too&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't give everything access to every secret. A service should be able to read only the specific secrets it actually needs. That way, if one service is compromised, the attacker gets that service's handful of secrets, not the master list of everything. This is the same principle that runs through all security, scope access narrowly so a single compromise has a small blast radius, applied to the credentials themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rotate, and make it painless enough that you actually do&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A secret that never changes is a secret that only accumulates risk, and the longer it lives the more places it may have leaked to. Rotation, regularly changing secrets, limits the damage of a leak you don't even know about yet. The reason nobody rotates with .env files is that it's agonizing. The reason proper secrets management matters is that it makes rotation a managed, sometimes automatic operation, which means it actually happens. Short-lived credentials that rotate automatically are the gold standard, because a leaked one expires fast on its own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't leak them at the other end either&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One easy-to-miss trap: secrets ending up in logs. An app that logs its config, or an error that dumps environment variables, can write your secrets straight into log files in plaintext, undoing all the careful storage. Be deliberate about never logging secrets, and treat logs as something that could leak, because they often have weaker access controls than you'd want for something holding credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mental model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Secrets are credentials, treat them like the keys they are. Never in git, ever, and rotate anything that slips in. Store them in a dedicated system, encrypted, with access control and an audit trail, not in plaintext files copied around. Give each thing access to only the secrets it needs. Rotate regularly, and use short-lived credentials where you can. And make sure they don't leak out through logs at the far end. The .env file was fine as a starting point. It was never supposed to be the whole plan, and the day it quietly became the plan is the day you took on risk you didn't decide to.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to Use MarketMuse for Natural Language Query Targeting in 2026</title>
      <dc:creator>leosociall-seointent</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:35:01 +0000</pubDate>
      <link>https://dev.to/leosociallseointent/how-to-use-marketmuse-for-natural-language-query-targeting-in-2026-mdn</link>
      <guid>https://dev.to/leosociallseointent/how-to-use-marketmuse-for-natural-language-query-targeting-in-2026-mdn</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://seointent.com/blog/marketmuse-for-natural-language-query-targeting" rel="noopener noreferrer"&gt;https://seointent.com/blog/marketmuse-for-natural-language-query-targeting&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Marketmuse for natural language query targeting works best when you treat it as a topic intelligence layer, not just a keyword tool — it maps what users actually ask, not just what they type.

- The five-step workflow in this article takes under 90 minutes and produces a content brief that covers conversational query variants your competitors are probably missing.

- MarketMuse's topic modeling outperforms generic keyword tools for NLQ work, but it needs clean prompt inputs to return useful outputs — garbage in, garbage out.

- If you need to run this workflow at scale across hundreds of pages, an AI SEO platform like SEOintent handles the automation layer MarketMuse doesn't offer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Marketmuse for natural language query targeting&lt;/strong&gt; is the practice of using MarketMuse's AI-driven topic modeling and content intelligence to identify, cluster, and optimize for the conversational, intent-rich questions real users ask search engines and AI assistants — rather than targeting isolated short-tail keywords. It treats queries as concepts with context, not strings to match.&lt;/p&gt;

&lt;p&gt;Search behavior shifted hard in 2024 and 2025. Google's AI Overviews, ChatGPT search, and Perplexity all reward content that answers whole questions, not keyword-stuffed paragraphs. That's why searches for &lt;em&gt;how to use MarketMuse for SEO&lt;/em&gt; in a post-NLQ context are spiking right now. Tools like Clearscope and Surfer SEO give you semantic keyword lists, and they're solid — but they don't map the conversational query structure the way MarketMuse does. Where they fall short is in showing you the full topic graph around a question. This article walks you through a real, repeatable workflow — not a feature tour. If you're building content at scale, also check out this &lt;a href="https://seointent.com/hub/programmatic-seo" rel="noopener noreferrer"&gt;programmatic SEO guide&lt;/a&gt; to see how NLQ targeting fits a larger automated content architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Marketmuse For Natural Language Query Targeting?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Marketmuse For Natural Language Query Targeting&lt;/strong&gt; is the use of MarketMuse's AI content research platform to surface the full intent landscape around a topic — identifying conversational questions, related concepts, and semantic variants that match how users phrase queries to search engines and AI-driven answer engines. It matters because standard keyword research misses the majority of how people actually ask questions.&lt;/p&gt;

&lt;p&gt;When you use MarketMuse as a &lt;em&gt;marketmuse SEO tool&lt;/em&gt; for this specific purpose, you're pulling from its proprietary knowledge graph to understand not just what people search but why — the context and the adjacent questions that define real user intent. Google's NLP systems, specifically BERT and MUM, evaluate content at this conceptual level, which is exactly what &lt;a href="https://developers.google.com/search/docs" rel="noopener noreferrer"&gt;Google's official SEO guide&lt;/a&gt; points toward when it emphasizes helpful, people-first content over keyword matching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use MarketMuse for Natural Language Query Targeting Specifically?
&lt;/h2&gt;

&lt;p&gt;MarketMuse earns its place in this workflow because its topic model is trained on millions of documents at the topical level, not just the keyword level. Unlike tools that score pages against keyword frequency, MarketMuse scores against conceptual completeness — which is almost exactly what Google's NLP pipeline evaluates. Its Content Score, Topic Navigator, and SERP analysis combine to give you a structured map of NLQ coverage gaps, something you'd spend hours building manually in a spreadsheet.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Topic Authority Mapping — MarketMuse scores your existing content against a full topic model, so you can see which conversational queries you're ranking for versus which ones you're invisible on. Pair this with the check AI search visibility tool to see how AI answer engines perceive your coverage.

- Competitive Gap Analysis at Query Level — It shows you which NLQ variants your competitors are covering that you're not, down to specific questions, not just broad topics. That's a direct playbook for content briefs.

- Automated Content Briefs — MarketMuse generates structured briefs that already include related questions and recommended concepts — essentially a natural language query targeting prompt baked into a document outline.

- Integration with Content Workflows — It connects with Google Docs and Word, which means writers get NLQ guidance inline rather than switching between tabs. Less friction means briefs actually get followed. For agencies running multiple clients, the agency SEO platform layer on top makes this scalable.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  How to Use MarketMuse for Natural Language Query Targeting: A 5-Step Workflow
&lt;/h2&gt;

&lt;p&gt;This workflow takes roughly 60-90 minutes for a single page and produces a content brief with full NLQ coverage mapped out. You need a MarketMuse account (Standard or higher for the full Topic Navigator), a target topic, and your current page URL if you're optimizing existing content. The step that trips most people up is Step 3 — mapping query intent tiers — because it requires judgment, not just tool outputs.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Step 1: Run a Topic Research Report. In MarketMuse, go to Research and enter your core topic — not a keyword, a topic. For example, "natural language query optimization for ecommerce" rather than "NLQ SEO." The report surfaces related questions, concepts, and variants. Pull the full Questions list and paste it into a working doc. Your seed prompt for filtering later: Cluster these questions by search intent: informational, navigational, transactional, and conversational. Flag any that imply voice search or AI assistant queries.

- Step 2: Build Your Query Cluster. From the Questions output, group related NLQ variants together. MarketMuse shows you which questions have high topic authority potential versus which are too thin to target alone. Combine thin questions into a single FAQ section rather than creating separate pages for each. Use this prompt in your brief-building process: List the 10 most semantically distinct user questions in this cluster and suggest the H2 or H3 where each fits naturally in a 2,000-word article.

- Step 3: Score Competitor Coverage. Run the Compete report for your top three SERP competitors on the core topic. MarketMuse shows their Content Score and which concepts they cover that you don't. Cross-reference this with OpenAI's ChatGPT by asking it your target NLQ and noting which competitor it cites — that's a signal of which coverage depth is winning in AI answer engines right now.

- Step 4: Write or Revise with the Content Brief. Export the MarketMuse content brief and use the Target Content Score as your quality bar. Every section should address at least one NLQ variant explicitly — the question as a subheading, the answer in the first sentence of the paragraph. This structure aligns with how Anthropic's Claude and similar LLMs extract and cite answers. Don't stuff all questions into one section — distribute them across the article in the order a user would logically ask them.

- Step 5: Validate and Publish. Before publishing, run your draft through MarketMuse's Optimize view to confirm you've hit or exceeded the Content Score target. Then check your metadata — a strong NLQ-optimized article still needs a title tag and meta description that reflect the conversational query. Use the free meta tag checker to confirm your tags are pulling the right signals. If your site has structured data in place, the free schema markup generator can add FAQ schema around your NLQ answers, which increases featured snippet eligibility.




**Pro tip:** Run your NLQ cluster through MarketMuse twice — once treating the topic as informational, once as commercial investigation — then merge the two question sets. You'll catch high-value buyer-intent queries that pure informational research consistently misses.


**Further reading:** If you want to take this workflow beyond individual pages and run it across entire content programs, these resources are worth bookmarking. Check the [SEOintent features](https://seointent.com/features) page for automation options, review the [agency partner program](https://seointent.com/agency-program) if you're managing multiple client sites, and see [sitemap analyzer](https://seointent.com/tools/sitemap-analyzer) to find which existing pages are already ranking for NLQ variants you could upgrade instead of creating new content.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqrvit3hss6rdonyy81kz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqrvit3hss6rdonyy81kz.jpeg" alt="Using MarketMuse for natural language query targeting — step-by-step" width="800" height="534"&gt;&lt;/a&gt;Photo by Stev3 Cassar on Pexels&lt;/p&gt;

&lt;h2&gt;
  
  
  What MarketMuse's Output Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;Here's what you get when you run a Topic Research report in MarketMuse for "natural language query targeting for SaaS content," then export the Questions list and filter it using the clustering prompt from Step 2. This is a realistic sample — not polished, not cherry-picked. The output usually needs one pass to remove redundant variants and one more to assign question-to-section mapping before it's usable in a brief.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Topic: Natural Language Query Targeting for SaaS Content&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content Score Target: 47 (Your current score: 29)



Top Questions Identified:

— What is natural language query targeting?

— How do I optimize SaaS content for conversational search?

— What tools help with NLQ SEO in 2026?

— How does Google understand natural language queries?

— What's the difference between NLQ and traditional keyword targeting?

— How do I write content for voice search queries?

— Does MarketMuse help with question-based SEO?

— What is intent-based content optimization?

— How do AI search engines rank conversational content?

— What questions should my content answer to rank in AI Overviews?



Top Missing Concepts vs. Competitors:

— BERT-based query interpretation

— Entity salience scoring

— Question schema markup

— AI answer engine optimization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The question list is genuinely useful — MarketMuse surfaces angles a standard keyword tool would never generate because it's working from a topic graph, not search volume data. What it doesn't do well is prioritize: you still have to decide which questions are worth a full H2 versus a two-sentence FAQ answer. The missing concepts list is where the real value sits, and most people scroll past it too quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  MarketMuse vs Other AI Tools for Natural Language Query Targeting
&lt;/h2&gt;

&lt;p&gt;The three main competitors here are Clearscope, Surfer SEO, and Frase. Clearscope gives you clean semantic keyword grading but doesn't map full question clusters — it's more of a coverage checker than a query planner. Surfer is stronger on technical SERP analysis but its NLQ features feel bolted on. Frase is the closest competitor for question-based research and is cheaper, but its topic model is shallower than MarketMuse's. MarketMuse wins for content teams doing deep-topic authority plays, but if you're a solo operator on a budget, Frase gets you 70% of the way there at a fraction of the cost.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ToolBest forWeaknessFree tier?


  **MarketMuse**Full topic authority mapping and NLQ cluster building at depthExpensive; steep learning curve on Topic NavigatorLimited free plan; paid starts at ~$149/mo
  ClearscopeContent grading against semantic keyword coverageNo conversational query clustering; weak on question intentNo free tier; demo only
  Surfer SEOSERP structure analysis and on-page scoringNLQ features are surface-level; content briefs miss deep question mappingNo free tier; trials available
  FraseBudget-friendly question research and SERP summarizationTopic model less complete; authority scoring less reliable$1 trial; paid from ~$15/mo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;MarketMuse is the right call when you're building topical authority across a content program and need the question-mapping depth to back it up. If you're doing one-off blog posts or working with a tight budget, it's overbuilt for that job and you'll pay for features you won't use.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; If you're comparing outputs from multiple tools, run the same topic through MarketMuse and Frase simultaneously and look at which questions appear in one but not the other — those exclusive queries are usually lower-competition NLQ targets worth prioritizing first.&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  3 Mistakes People Make With Marketmuse For Natural Language Query Targeting&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Most mistakes with this workflow come from treating MarketMuse like a keyword density tool rather than a topic intelligence platform. People rush the research phase, skip the competitor coverage step, or over-optimize by cramming every question into one page instead of distributing across a content cluster. The common thread is impatience — the tool rewards thoroughness. Here's what to avoid — and what to do instead:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Mistake 1: Targeting one NLQ per page and ignoring clusters. Single questions rarely have enough search volume to justify standalone pages. Group semantically related questions into one well-structured page with clear subheadings — it's how Google's BERT evaluates topical completeness. Use MarketMuse's Questions list to build the cluster first, then plan your page architecture. If you're managing this across a large site, the sitemap analyzer can show you where existing pages already cover NLQ variants you could consolidate.

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Mistake 2: Accepting MarketMuse's Content Score as the only quality bar. The Content Score measures conceptual coverage, not answer quality. You can hit a score of 55 with thin, generic answers to each question and still rank nowhere. Write the actual answer to each NLQ before worrying about the score — a complete, specific answer almost always hits the required concepts naturally. Run your content through the AI text detector too, since AI-generated filler inflates MarketMuse scores without adding real answer depth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mistake 3: Skipping the API documentation when integrating MarketMuse outputs into automated workflows. If you're piping MarketMuse data into a content automation pipeline, the prompt formatting matters a lot. Refer to the Claude API docs or the ChatGPT API documentation for structured prompt formatting that handles MarketMuse JSON exports cleanly — malformed prompts produce off-topic completions that waste both API credits and time.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Automate Natural Language Query Targeting With SEOintent&lt;br&gt;
&lt;/h2&gt;


&lt;p&gt;MarketMuse handles research and brief-building well, but it stops short of execution at scale. SEOintent's &lt;em&gt;automated natural language query targeting&lt;/em&gt; layer picks up where MarketMuse leaves off — the Query Cluster Automation feature ingests your topic list, maps NLQ variants at scale, and generates ready-to-publish briefs without manual prompt-building for each page. The AI Visibility Scoring feature then monitors how AI answer engines like Perplexity and ChatGPT search are citing your content against the NLQ targets you set. Check the &lt;a href="https://seointent.com/features" rel="noopener noreferrer"&gt;SEOintent features&lt;/a&gt; page for the full breakdown, and if you're running an agency, the &lt;a href="https://seointent.com/pricing" rel="noopener noreferrer"&gt;SEOintent pricing&lt;/a&gt; tiers are built around multi-client volume rather than per-page billing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions About Marketmuse For Natural Language Query Targeting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is MarketMuse good for optimizing content for AI search engines like Perplexity and ChatGPT?
&lt;/h3&gt;

&lt;p&gt;Yes, with caveats. MarketMuse's topic modeling aligns closely with how AI answer engines evaluate topical completeness, so content that scores well in MarketMuse tends to get cited more in AI-generated answers. That said, MarketMuse doesn't directly track AI citation rates — for that, you'd want to &lt;a href="https://seointent.com/tools/ai-visibility-checker" rel="noopener noreferrer"&gt;check AI search visibility&lt;/a&gt; separately to see where you're being pulled into AI Overviews or LLM responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between using MarketMuse for NLQ targeting versus standard keyword research?
&lt;/h3&gt;

&lt;p&gt;Standard keyword research gives you search volume and difficulty scores for specific phrases. MarketMuse for NLQ targeting gives you the full conceptual landscape around a topic — including questions users ask at different stages of intent, not just the phrases they type. It's the difference between knowing "people search this phrase 1,200 times a month" and knowing "people who search this topic also need answers to these seven adjacent questions before they convert." The second view produces better content.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long does it take to see results from MarketMuse NLQ optimization?
&lt;/h3&gt;

&lt;p&gt;For new pages, expect 3-6 months before NLQ-targeted content starts pulling consistent organic traffic, depending on your domain authority and the competition level of your topic cluster. For existing pages that you upgrade with better NLQ coverage, ranking improvements can appear within 4-8 weeks since Google is already indexing your domain. Structured data like FAQ schema accelerates featured snippet eligibility — use the &lt;a href="https://seointent.com/tools/schema-generator" rel="noopener noreferrer"&gt;free schema markup generator&lt;/a&gt; to add it without touching your CMS code directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use MarketMuse with other AI writing tools in the same workflow?
&lt;/h3&gt;

&lt;p&gt;Absolutely — that's actually how most teams use it. MarketMuse handles the research and brief layer; then you pass the brief to an AI writing assistant like &lt;a href="https://www.anthropic.com/claude" rel="noopener noreferrer"&gt;Anthropic's Claude&lt;/a&gt; or a similar model for drafting. The key is passing the full MarketMuse brief as context, not just the target keyword — that's what keeps the AI output aligned with the NLQ coverage requirements the brief specifies. Don't expect the AI draft to hit MarketMuse's Content Score on the first pass; plan for one editing round focused purely on concept coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is MarketMuse worth the cost compared to cheaper alternatives for NLQ work?
&lt;/h3&gt;

&lt;p&gt;For solo bloggers or small sites, probably not. Frase covers most of the question-research functionality at a much lower price point. MarketMuse justifies its cost when you're managing a content program across dozens of topic clusters, need deep competitive benchmarking, or are working in a high-competition niche where content authority differences are measured in single percentage points. If you're running an agency with multiple clients in competitive verticals, the ROI case is strong — the &lt;a href="https://seointent.com/agency-program" rel="noopener noreferrer"&gt;agency partner program&lt;/a&gt; also offers tiered pricing that makes the per-client cost more manageable.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do MarketMuse prompts work for natural language query targeting?
&lt;/h3&gt;

&lt;p&gt;MarketMuse itself doesn't use a traditional prompt interface — it's a structured research platform, not a chat tool. When people refer to &lt;em&gt;marketmuse prompts&lt;/em&gt; in the context of NLQ targeting, they usually mean the prompts you write in ChatGPT, Claude, or another LLM to process MarketMuse's output — clustering questions, mapping intent tiers, or drafting answer paragraphs from the exported brief data. The prompts in Step 1 and Step 2 of this article are the ones I'd start with. Keep them specific to the MarketMuse data you're feeding in — vague prompts produce generic clusters that don't reflect what the topic model actually found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does MarketMuse integrate with WordPress or other CMS platforms?
&lt;/h3&gt;

&lt;p&gt;MarketMuse integrates directly with Google Docs and Microsoft Word via browser extensions, which covers most editorial workflows. There's no native WordPress plugin, but you can export briefs as structured documents and paste content directly into any CMS. For teams running large-scale CMS publishing pipelines, the better approach is to use MarketMuse for research and brief generation, then pipe outputs into a dedicated &lt;a href="https://seointent.com/ai-seo-services" rel="noopener noreferrer"&gt;AI SEO platform&lt;/a&gt; that has native CMS integrations and can handle bulk publishing workflows without manual copy-paste for each page.&lt;/p&gt;

&lt;h2&gt;
  
  
  More AI SEO Workflows
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to Use MarketMuse for Keyword Research in 2026&lt;/li&gt;
&lt;li&gt;How to Use MarketMuse for Keyword Clustering in 2026&lt;/li&gt;
&lt;li&gt;How to Use MarketMuse for Competitor Keyword Analysis in 2026&lt;/li&gt;
&lt;li&gt;How to Use MarketMuse for Long-Tail Keyword Discovery in 2026&lt;/li&gt;
&lt;li&gt;How to Use MarketMuse for Search Intent Classification in 2026&lt;/li&gt;
&lt;li&gt;How to Use MarketMuse for Keyword Gap Analysis in 2026&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>marketmuse</category>
      <category>naturallanguagequerytargeting</category>
      <category>seo</category>
      <category>ai</category>
    </item>
    <item>
      <title>Explainability in LLM: Challenges and Opportunities</title>
      <dc:creator>shashank ms</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:34:27 +0000</pubDate>
      <link>https://dev.to/shashank_ms_6a35baa4be138/explainability-in-llm-challenges-and-opportunities-ke7</link>
      <guid>https://dev.to/shashank_ms_6a35baa4be138/explainability-in-llm-challenges-and-opportunities-ke7</guid>
      <description>&lt;p&gt;We are going to build a lightweight explainability tracer that forces an LLM to emit a structured reasoning trace, confidence score, and source attribution tags alongside every answer. This gives developers a transparent audit log for debugging model behavior without proprietary black-box tools.&lt;/p&gt;

&lt;h2 id="what-youll-need"&gt;What you'll need&lt;/h2&gt;

&lt;p&gt;Python 3.10 or newer, the OpenAI SDK, and an Oxlo.ai API key. Install the SDK with &lt;code&gt;pip install openai&lt;/code&gt;, then grab a free key from &lt;a href="https://portal.oxlo.ai" rel="noopener noreferrer"&gt;https://portal.oxlo.ai&lt;/a&gt;. The free tier includes 60 requests per day, which is plenty for prototyping this tracer.&lt;/p&gt;

&lt;h2 id="step-1-configure-the-oxlo.ai-client"&gt;Step 1: Configure the Oxlo.ai client&lt;/h2&gt;

&lt;p&gt;I start by initializing the OpenAI-compatible client pointing at Oxlo.ai. I pull the API key from an environment variable so it never leaks into source control.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key=os.getenv("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)

# Quick connectivity check
response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Say OK"},
    ],
)
print(response.choices[0].message.content)&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-2-prepare-a-mock-knowledge-base"&gt;Step 2: Prepare a mock knowledge base&lt;/h2&gt;

&lt;p&gt;To demonstrate source attribution, I need documents to retrieve from. I hardcode three short chunks so the tutorial stays reproducible without setting up a vector database.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;KNOWLEDGE_BASE = [
    {
        "id": "doc-001",
        "text": "Solar panels convert sunlight into electricity using photovoltaic cells. Efficiency rates typically range from 15 to 22 percent."
    },
    {
        "id": "doc-002",
        "text": "Wind turbines generate power through rotational energy. Offshore farms achieve higher capacity factors than onshore installations."
    },
    {
        "id": "doc-003",
        "text": "Nuclear fission releases heat by splitting uranium atoms. Modern reactors produce minimal carbon emissions during operation."
    },
]

def retrieve_chunks(query: str, top_k: int = 2):
    # In production, swap this for embedding search.
    # Oxlo.ai offers BGE-Large and E5-Large embeddings for that.
    return KNOWLEDGE_BASE[:top_k]

query = "Which renewable source works best at sea?"
context_chunks = retrieve_chunks(query)
context_text = "\n\n".join([f"[{c['id']}] {c['text']}" for c in context_chunks])&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-3-write-the-explainability-system-prompt"&gt;Step 3: Write the explainability system prompt&lt;/h2&gt;

&lt;p&gt;The system prompt is the critical piece. It instructs the model to wrap its chain of thought, final answer, and explainability metadata in strict XML tags so we can parse them deterministically.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SYSTEM_PROMPT = """You are an Explainability Tracer. Your job is to answer the user based ONLY on the provided context documents.

Follow this exact output format:

&amp;lt;thinking&amp;gt;
1. List each document ID and whether it is relevant.
2. Note any uncertainties or contradictions.
3. Outline your reasoning before concluding.
&amp;lt;/thinking&amp;gt;

&amp;lt;answer&amp;gt;
Provide a concise, accurate answer to the user's question.
&amp;lt;/answer&amp;gt;

&amp;lt;explainability&amp;gt;
confidence: 0.0 to 1.0
sources_used: list of document IDs you relied on
bias_flags: note any potential gaps in the provided context
&amp;lt;/explainability&amp;gt;

Do not deviate from these tags."""&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-4-build-the-request-pipeline"&gt;Step 4: Build the request pipeline&lt;/h2&gt;

&lt;p&gt;I assemble the user message by injecting the retrieved context, then call Llama 3.3 70B through Oxlo.ai. This model handles long context and structured instructions reliably, and because Oxlo.ai charges per request rather than per token, adding a large system prompt does not inflate the cost.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;user_message = f"""Context documents:
{context_text}

User question: {query}

Remember to use the required XML tags in your response."""

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": user_message},
    ],
)

raw_output = response.choices[0].message.content
print(raw_output)&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-5-parse-and-display-the-trace"&gt;Step 5: Parse and display the trace&lt;/h2&gt;

&lt;p&gt;Raw XML is not enough. I want a clean dictionary I can log to JSON. I use regular expressions to extract the three blocks and pretty-print them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import re

def parse_explainability(text: str) -&amp;gt; dict:
    pattern = r"&amp;lt;thinking&amp;gt;(.*?)&amp;lt;/thinking&amp;gt;.*?&amp;lt;answer&amp;gt;(.*?)&amp;lt;/answer&amp;gt;.*?&amp;lt;explainability&amp;gt;(.*?)&amp;lt;/explainability&amp;gt;"
    m = re.search(pattern, text, re.DOTALL)
    if not m:
        return {"raw": text, "parsed": False}
    return {
        "parsed": True,
        "thinking": m.group(1).strip(),
        "answer": m.group(2).strip(),
        "explainability": m.group(3).strip(),
    }

result = parse_explainability(raw_output)

print("=== THINKING TRACE ===")
print(result["thinking"])
print("\n=== FINAL ANSWER ===")
print(result["answer"])
print("\n=== EXPLAINABILITY METADATA ===")
print(result["explainability"])&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="run-it"&gt;Run it&lt;/h2&gt;

&lt;p&gt;Here is the complete script. Save it as &lt;code&gt;tracer.py&lt;/code&gt;, export &lt;code&gt;OXLO_API_KEY&lt;/code&gt;, and run &lt;code&gt;python tracer.py&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import os
import re
from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key=os.getenv("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)

KNOWLEDGE_BASE = [
    {"id": "doc-001", "text": "Solar panels convert sunlight into electricity using photovoltaic cells. Efficiency rates typically range from 15 to 22 percent."},
    {"id": "doc-002", "text": "Wind turbines generate power through rotational energy. Offshore farms achieve higher capacity factors than onshore installations."},
    {"id": "doc-003", "text": "Nuclear fission releases heat by splitting uranium atoms. Modern reactors produce minimal carbon emissions during operation."},
]

SYSTEM_PROMPT = """You are an Explainability Tracer. Your job is to answer the user based ONLY on the provided context documents.

Follow this exact output format:

&amp;lt;thinking&amp;gt;
1. List each document ID and whether it is relevant.
2. Note any uncertainties or contradictions.
3. Outline your reasoning before concluding.
&amp;lt;/thinking&amp;gt;

&amp;lt;answer&amp;gt;
Provide a concise, accurate answer to the user's question.
&amp;lt;/answer&amp;gt;

&amp;lt;explainability&amp;gt;
confidence: 0.0 to 1.0
sources_used: list of document IDs you relied on
bias_flags: note any potential gaps in the provided context
&amp;lt;/explainability&amp;gt;

Do not deviate from these tags."""

def retrieve_chunks(query: str, top_k: int = 2):
    return KNOWLEDGE_BASE[:top_k]

def parse_explainability(text: str) -&amp;gt; dict:
    pattern = r"&amp;lt;thinking&amp;gt;(.*?)&amp;lt;/thinking&amp;gt;.*?&amp;lt;answer&amp;gt;(.*?)&amp;lt;/answer&amp;gt;.*?&amp;lt;explainability&amp;gt;(.*?)&amp;lt;/explainability&amp;gt;"
    m = re.search(pattern, text, re.DOTALL)
    if not m:
        return {"raw": text, "parsed": False}
    return {
        "parsed": True,
        "thinking": m.group(1).strip(),
        "answer": m.group(2).strip(),
        "explainability": m.group(3).strip(),
    }

if __name__ == "__main__":
    query = "Which renewable source works best at sea?"
    chunks = retrieve_chunks(query)
    context_text = "\n\n".join([f"[{c['id']}] {c['text']}" for c in chunks])

    user_message = f"""Context documents:
{context_text}

User question: {query}

Remember to use the required XML tags in your response."""

    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )

    raw_output = response.choices[0].message.content
    result = parse_explainability(raw_output)

    print("=== THINKING TRACE ===")
    print(result["thinking"])
    print("\n=== FINAL ANSWER ===")
    print(result["answer"])
    print("\n=== EXPLAINABILITY METADATA ===")
    print(result["explainability"])&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Example output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;=== THINKING TRACE ===
1. doc-001 discusses solar panels on land, not specifically sea. It is partially relevant but does not address offshore conditions.
2. doc-002 directly mentions offshore wind farms and higher capacity factors at sea. It is highly relevant.
3. doc-003 covers nuclear, which is not renewable in the same category and does not mention sea-based deployment.
There are no contradictions, but the context lacks data on tidal or wave energy.

=== FINAL ANSWER ===
Wind power is the renewable source that works best at sea, as offshore wind turbines achieve higher capacity factors than onshore installations.

=== EXPLAINABILITY METADATA ===
confidence: 0.92
sources_used: doc-002
bias_flags: Context omits tidal and wave energy technologies, which could also be relevant for sea-based renewable power.&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="wrap-up"&gt;Wrap-up&lt;/h2&gt;

&lt;p&gt;From here, swap the model string to &lt;code&gt;deepseek-r1-671b&lt;/code&gt; or &lt;code&gt;qwen-3-32b&lt;/code&gt; on Oxlo.ai to compare how different architectures phrase their reasoning traces. You can also replace the hardcoded &lt;code&gt;retrieve_chunks&lt;/code&gt; function with a real embedding search using Oxlo.ai's BGE-Large endpoint.&lt;/p&gt;

&lt;p&gt;Another practical upgrade is wrapping this logic in FastAPI middleware so every chat completion in your application automatically generates and logs an explainability trace to a structured store like SQLite or ClickHouse.&lt;/p&gt;

</description>
      <category>learnai</category>
      <category>oxlo</category>
      <category>ai</category>
    </item>
    <item>
      <title>Explainable Causal Reinforcement Learning for circular manufacturing supply chains with ethical auditability baked in</title>
      <dc:creator>Rikin Patel</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:34:09 +0000</pubDate>
      <link>https://dev.to/rikinptl/explainable-causal-reinforcement-learning-for-circular-manufacturing-supply-chains-with-ethical-3i8g</link>
      <guid>https://dev.to/rikinptl/explainable-causal-reinforcement-learning-for-circular-manufacturing-supply-chains-with-ethical-3i8g</guid>
      <description>&lt;h1&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1586528116311-ad8dd3c8310d%3Fixlib%3Drb-4.0.3%26auto%3Dformat%26fit%3Dcrop%26w%3D1200%26q%3D80" alt="Circular Supply Chain" width="1200" height="800"&gt;
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Explainable Causal Reinforcement Learning for circular manufacturing supply chains with ethical auditability baked in
&lt;/h1&gt;

&lt;p&gt;It started, as most of my rabbit holes do, with a frustration. I was building a standard reinforcement learning (RL) agent to optimize inventory levels in a simulated manufacturing network. The agent was brilliant—it reduced waste by 23% and cut holding costs by nearly 30%. But when I tried to explain &lt;em&gt;why&lt;/em&gt; it made a specific decision to a stakeholder, I hit a wall. The policy was a black box. The agent had learned to send excess raw material to a downstream partner, but I couldn't tell if it was because of a genuine supply surplus or because of a subtle, unintended bias in the reward function that favored that specific partner.&lt;/p&gt;

&lt;p&gt;This led me down a path that completely reshaped how I think about AI in industrial settings. I realized that for AI to be truly transformative in complex, ethically-charged environments like circular manufacturing supply chains, it needs to do more than just optimize. It needs to &lt;em&gt;understand&lt;/em&gt; the causal mechanisms at play, and it needs to be &lt;em&gt;accountable&lt;/em&gt; for its actions. This is the story of how I learned to build an Explainable Causal Reinforcement Learning (ECRL) framework, and how I baked ethical auditability directly into the architecture, rather than bolting it on as an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Background: Why Causal and Why Explainable?
&lt;/h2&gt;

&lt;p&gt;In my research of traditional RL applications in supply chains, I discovered a fundamental flaw: they treat correlations as if they were causations. A standard RL agent sees a spike in demand and learns to increase production. But it doesn't know &lt;em&gt;why&lt;/em&gt; the demand spiked. Was it a seasonal trend? A one-off promotional event? Or a systemic shock like a port closure? Without this causal understanding, the agent is fragile. It will fail catastrophically when the environment shifts in ways not represented in its training data.&lt;/p&gt;

&lt;p&gt;This is where Causal Reinforcement Learning (CRL) comes in. Instead of learning a policy directly from state-action pairs, CRL learns a &lt;strong&gt;Structural Causal Model (SCM)&lt;/strong&gt; of the environment. This model explicitly encodes the cause-and-effect relationships between variables. For example, it might learn that &lt;code&gt;Supplier_Reliability -&amp;gt; Production_Output -&amp;gt; Waste_Level&lt;/code&gt;. This allows the agent to reason about interventions—"What would happen if I switched suppliers?"—even if that exact scenario was never seen during training.&lt;/p&gt;

&lt;p&gt;But causal models alone are not enough. They are often complex, non-linear graphs that are as hard to interpret as a neural network. This is where Explainable AI (XAI) comes in. I needed to build a system that could not only make optimal decisions but also generate human-understandable explanations for those decisions.&lt;/p&gt;

&lt;p&gt;My exploration of the literature revealed a powerful convergence: using &lt;strong&gt;causal inference&lt;/strong&gt; as the foundation for &lt;strong&gt;explanations&lt;/strong&gt;. Instead of using post-hoc explainers like SHAP (SHapley Additive exPlanations), which are often approximations and can be misleading, I could use the causal graph itself to generate &lt;em&gt;counterfactual&lt;/em&gt; explanations. "You would have produced 15% less waste if you had switched to Supplier B two days earlier."&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Details: Building the ECRL Agent
&lt;/h2&gt;

&lt;p&gt;Let me walk you through the core components of the framework I built. The architecture has three main layers: the &lt;strong&gt;Causal Discovery Module&lt;/strong&gt;, the &lt;strong&gt;RL Policy Engine&lt;/strong&gt;, and the &lt;strong&gt;Explanation &amp;amp; Audit Interface&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Causal Discovery Module
&lt;/h3&gt;

&lt;p&gt;The first step is to learn the SCM from historical data. This is the most challenging part. In my experimentation, I found that using a hybrid approach works best. I start with a domain expert to define the &lt;em&gt;skeleton&lt;/em&gt; of the causal graph (the known relationships), and then I use a data-driven algorithm like &lt;strong&gt;PC (Peter-Clark)&lt;/strong&gt; or &lt;strong&gt;GES (Greedy Equivalence Search)&lt;/strong&gt; to discover additional, non-obvious causal links.&lt;/p&gt;

&lt;p&gt;Here’s a simplified Python example using the &lt;code&gt;gCastle&lt;/code&gt; library to discover causal structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;castle&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;castle.algorithms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PC&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="c1"&gt;# Sample data: [supplier_lead_time, inventory_level, production_output, waste]
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lead_time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inventory&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;waste&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Inject a known causal relationship: production -&amp;gt; waste
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;waste&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;waste&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Run PC algorithm for causal discovery
&lt;/span&gt;&lt;span class="n"&gt;pc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;causal_matrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;causal_matrix&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Discovered Causal Graph (DAG):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;causal_matrix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Output will show a directed edge from 'production' to 'waste'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Learning Insight:&lt;/strong&gt; While exploring the PC algorithm, I realized that the order of variables matters significantly. The algorithm's output can be unstable if you don't provide a robust prior. In my experience, encoding domain knowledge (e.g., "supplier lead time cannot be &lt;em&gt;caused&lt;/em&gt; by our internal waste") as a &lt;code&gt;prior_knowledge&lt;/code&gt; constraint drastically improved the accuracy of the discovered graph.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The RL Policy Engine with Causal Induction
&lt;/h3&gt;

&lt;p&gt;Now, the core of the agent. Instead of a standard Deep Q-Network (DQN) that takes raw state features, my agent maintains a latent representation of the causal state. This is achieved by using a &lt;strong&gt;Causal Inductive Bias&lt;/strong&gt; in the neural network architecture. I used a custom &lt;code&gt;CausalDQN&lt;/code&gt; that incorporates the learned adjacency matrix into its attention mechanism.&lt;/p&gt;

&lt;p&gt;The logic is: the agent doesn't just see the state; it sees the &lt;em&gt;causal state&lt;/em&gt;, which is a representation of the current values of all variables &lt;em&gt;and&lt;/em&gt; their causal parents. This forces the policy to focus on the root causes, not just the symptoms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CausalDQN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;causal_adj_matrix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;causal_adj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;causal_adj_matrix&lt;/span&gt;  &lt;span class="c1"&gt;# Pre-learned adjacency matrix
&lt;/span&gt;
        &lt;span class="c1"&gt;# This layer applies a causal mask to the input state
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;causal_attention&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Apply causal mask: only allow information flow from causal parents
&lt;/span&gt;        &lt;span class="n"&gt;masked_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matmul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;causal_adj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;causal_attention&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;masked_state&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; In my testing, this causal masking forced the agent to learn a policy that is robust to &lt;em&gt;distributional shift&lt;/em&gt;. For example, if the causal graph says &lt;code&gt;Waste&lt;/code&gt; is caused by &lt;code&gt;Production_Volume&lt;/code&gt; and &lt;code&gt;Machine_Efficiency&lt;/code&gt;, then the agent will automatically adjust its policy if &lt;code&gt;Machine_Efficiency&lt;/code&gt; drops, even if &lt;code&gt;Production_Volume&lt;/code&gt; remains constant. A standard RL agent would not adapt as gracefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ethical Auditability and Counterfactual Explanations
&lt;/h3&gt;

&lt;p&gt;This is the part that I'm most proud of. I wanted to build ethical auditability &lt;em&gt;in&lt;/em&gt;, not just as a reporting tool. This means the system must be able to answer "What if?" questions and provide a formal, causal justification for its decisions.&lt;/p&gt;

&lt;p&gt;I integrated a &lt;strong&gt;DoWhy&lt;/strong&gt; library for causal inference to generate counterfactual explanations. When the agent makes a decision, we can query it: "Why did you choose to reroute materials to Facility B?"&lt;/p&gt;

&lt;p&gt;The system responds by performing a counterfactual intervention on the causal graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dowhy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dowhy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CausalModel&lt;/span&gt;

&lt;span class="c1"&gt;# Assume we have a causal model 'model' and a graph 'graph'
# and data 'data'
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;explain_decision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;causal_graph&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Identify the target variable (e.g., total_waste)
&lt;/span&gt;    &lt;span class="c1"&gt;# 2. Identify the action taken (e.g., reroute_to_B = 1)
&lt;/span&gt;
    &lt;span class="c1"&gt;# Create a causal model for the current situation
&lt;/span&gt;    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CausalModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;treatment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reroute_to_B&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total_waste&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;causal_graph&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Identify the causal effect of the action
&lt;/span&gt;    &lt;span class="n"&gt;identified_estimand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;identify_effect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Estimate the effect (using a method like backdoor.linear_regression)
&lt;/span&gt;    &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;estimate_effect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identified_estimand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backdoor.linear_regression&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Generate a counterfactual: what if we had NOT rerouted to B?
&lt;/span&gt;    &lt;span class="n"&gt;counterfactual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;counterfactual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reroute_to_B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_waste&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;explanation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rerouting to Facility B reduced total waste by &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; units. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; \
                  &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If we had not rerouted, waste would have been &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;counterfactual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; units higher.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;explanation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ethical Auditability in Action:&lt;/strong&gt; This goes beyond simple transparency. It provides &lt;em&gt;accountability&lt;/em&gt;. If an auditor asks, "Why was this batch of materials scrapped instead of recycled?", the system can provide a causal chain: "Scrapping was chosen because the causal model predicted a 95% probability of contamination based on the sensor data &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and &lt;code&gt;z&lt;/code&gt; from the previous process. The counterfactual analysis shows that recycling would have led to a batch failure, costing $X more."&lt;/p&gt;

&lt;p&gt;By making the &lt;em&gt;counterfactual&lt;/em&gt; explicit, we turn the AI from a black-box decision-maker into a tool that can be interrogated and challenged, which is the core of ethical auditability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Applications: Circular Manufacturing
&lt;/h2&gt;

&lt;p&gt;I tested this framework on a simulated circular supply chain for electronic components. The chain had three loops: &lt;strong&gt;Manufacturing&lt;/strong&gt;, &lt;strong&gt;Recycling&lt;/strong&gt;, and &lt;strong&gt;Refurbishment&lt;/strong&gt;. The agent's goal was to maximize profit while minimizing virgin material usage and e-waste.&lt;/p&gt;

&lt;p&gt;Here’s where the ECRL shined:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Pricing for Recycled Materials:&lt;/strong&gt; The agent learned a causal link between the price of virgin lithium and the purity of recycled lithium. It discovered that when virgin prices were high, it was causally optimal to invest more in advanced recycling purification, even if it temporarily slowed production. A non-causal RL agent failed to see this long-term, indirect benefit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Proactive Maintenance:&lt;/strong&gt; By understanding that &lt;code&gt;Machine_Vibration -&amp;gt; Bearing_Failure -&amp;gt; Production_Stop -&amp;gt; Waste&lt;/code&gt;, the agent learned to trigger maintenance not on a fixed schedule, but based on a causal risk assessment. This reduced unplanned downtime by 40% compared to a threshold-based system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ethical Sourcing:&lt;/strong&gt; I explicitly modeled a causal path &lt;code&gt;Supplier_Country -&amp;gt; Regulatory_Compliance -&amp;gt; Ethical_Score&lt;/code&gt;. The agent was then able to make cost-optimal decisions that were also constrained by a minimum ethical score. When asked to explain a decision to source from a slightly more expensive supplier, the agent could state: "Supplier B has an ethical score of 8.5, causally determined by its high compliance rate. Choosing Supplier A would have increased profit by 2% but would have violated the ethical constraint, leading to a predicted reputational risk cost of $1M."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Challenges and Solutions
&lt;/h2&gt;

&lt;p&gt;This journey was not smooth sailing. I encountered several significant challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 1: Causal Discovery from Noisy Data&lt;/strong&gt;&lt;br&gt;
Real-world supply chain data is messy. Sensor failures, missing values, and human errors create noise that can destroy causal discovery algorithms. The PC algorithm would often output nonsensical edges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; I implemented a &lt;strong&gt;Bootstrap Aggregation (Bagging)&lt;/strong&gt; approach for causal discovery. I ran the PC algorithm on 100 different bootstrap samples of the data and only kept edges that appeared in at least 90% of the runs. This significantly increased the robustness of the causal graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 2: The "Reward Hacking" Problem with Ethical Constraints&lt;/strong&gt;&lt;br&gt;
I initially tried to incorporate ethics by adding a penalty term to the reward function. The agent learned to game this by finding ways to get high rewards that technically didn't violate the penalty but were clearly against the spirit of the rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; I moved away from reward shaping and instead implemented a &lt;strong&gt;Constrained MDP (CMDP)&lt;/strong&gt;. The ethical rules became hard constraints that the agent could not violate, rather than soft penalties. I used a Lagrangian relaxation method to solve this. This made the ethical behavior a &lt;em&gt;requirement&lt;/em&gt;, not an option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 3: Scalability of Counterfactual Explanations&lt;/strong&gt;&lt;br&gt;
Generating counterfactual explanations using DoWhy was computationally expensive. For a large supply chain graph with hundreds of variables, it was too slow for real-time querying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; I pre-computed a library of "causal pathways" for critical decisions. For any new decision, the system would retrieve the relevant causal sub-graph and only run the counterfactual inference on that small sub-graph. This reduced the explanation time from seconds to milliseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Directions: Quantum and Agentic AI
&lt;/h2&gt;

&lt;p&gt;My exploration of this field has revealed some exciting frontiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quantum Computing for Causal Inference:&lt;/strong&gt; Causal discovery is a combinatorial optimization problem. As I was experimenting with quantum annealing for other optimization tasks, I realized it has massive potential here. I'm currently exploring using &lt;strong&gt;Quadratic Unconstrained Binary Optimization (QUBO)&lt;/strong&gt; formulations to solve the causal discovery problem on a D-Wave quantum computer. The promise is that quantum annealing could find the globally optimal causal graph, whereas classical algorithms often get stuck in local optima.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic AI for Self-Healing Supply Chains:&lt;/strong&gt; The next step is to make these ECRL agents fully agentic. Instead of just recommending actions, they will be able to execute multi-step plans autonomously. Imagine an agent that not only detects a causal disruption (e.g., a port closure) but also autonomously negotiates with alternative suppliers, re-routes logistics, and adjusts production schedules, all while providing a full causal audit trail of its actions. This is the ultimate goal of "autonomous supply chain management."&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Learning Journey Continues
&lt;/h2&gt;

&lt;p&gt;This deep dive into Explainable Causal Reinforcement Learning has fundamentally changed my perspective on AI in complex systems. I've learned that the true power of AI is not just in its predictive accuracy, but in its ability to &lt;em&gt;reason&lt;/em&gt; about the world and &lt;em&gt;justify&lt;/em&gt; its actions.&lt;/p&gt;

&lt;p&gt;The combination of causal reasoning and explainability creates a powerful synergy. The causal model provides the &lt;em&gt;structure&lt;/em&gt; for understanding, and the explainability framework provides the &lt;em&gt;communication&lt;/em&gt; of that understanding. When you add ethical constraints as hard, structural requirements, you get a system that is not just intelligent, but also trustworthy and accountable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways from My Experimentation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Don't ignore causality.&lt;/strong&gt; If you're applying RL to any real-world system, spend the time to build a causal model. It's the difference between a brittle model and a robust one.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Explainability is a feature, not an afterthought.&lt;/strong&gt; Build your explanation mechanism into the architecture, not as a post-hoc script. Counterfactual explanations are far more powerful than simple feature importance.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Ethics must be enforced, not suggested.&lt;/strong&gt; Soft penalties in reward functions are easily gamed. Use hard constraints to enforce ethical boundaries.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The future is agentic.&lt;/strong&gt; The combination of causal reasoning, RL, and agentic AI will lead to systems that can not only make decisions but also act on them in the real world, with full accountability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is not the end of the story. It's a snapshot of a learning journey that is very much in progress. As I continue to explore the intersection of quantum computing and agentic AI, I'm excited to see how these powerful tools can be combined to build a more sustainable, efficient, and ethical industrial future. The code, the models, and the insights are all part of a larger puzzle, and I'm just getting started on finding the next piece.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>quantumcomputing</category>
      <category>agenticai</category>
    </item>
    <item>
      <title>Building a Coreference Resolution Tool with LLM: A Step-by-Step Guide</title>
      <dc:creator>shashank ms</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:33:50 +0000</pubDate>
      <link>https://dev.to/shashank_ms_6a35baa4be138/building-a-coreference-resolution-tool-with-llm-a-step-by-step-guide-4m6a</link>
      <guid>https://dev.to/shashank_ms_6a35baa4be138/building-a-coreference-resolution-tool-with-llm-a-step-by-step-guide-4m6a</guid>
      <description>&lt;p&gt;Coreference resolution maps pronouns and descriptive phrases back to the real-world entities they refer to. A lightweight LLM-based resolver is enough to clean up messy transcripts, legal documents, or chat logs without training a custom spaCy model. In this guide I will wire up a working resolver using Oxlo.ai and the OpenAI SDK, taking advantage of flat request-based pricing that stays predictable even when we feed it long paragraphs.&lt;/p&gt;

&lt;h2 id="what-youll-need"&gt;What you'll need&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.10 or newer&lt;/li&gt;
&lt;li&gt;The OpenAI SDK: &lt;code&gt;pip install openai&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An Oxlo.ai API key from &lt;a href="https://portal.oxlo.ai" rel="noopener noreferrer"&gt;https://portal.oxlo.ai&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="step-1-client"&gt;Step 1: Configure the Oxlo.ai client&lt;/h2&gt;

&lt;p&gt;I start by instantiating the OpenAI-compatible client pointing at Oxlo.ai. I use Llama 3.3 70B because it follows structured instructions reliably and handles long documents without cold starts.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key="YOUR_OXLO_API_KEY"
)&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-2-prompt"&gt;Step 2: Define the system prompt&lt;/h2&gt;

&lt;p&gt;The system prompt forces the model to return only JSON containing entity clusters. Each cluster lists every mention that refers to the same entity, with the most specific mention chosen as the representative.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SYSTEM_PROMPT = """You are a coreference resolution engine. Given a user text, identify all entity clusters. Each cluster groups mentions that refer to the same real-world entity.

Return strictly JSON in this exact structure:
{
  "clusters": [
    {
      "representative": "the clearest full name or noun phrase",
      "mentions": ["span 1", "span 2", "span 3"]
    }
  ]
}

Rules:
- Include pronouns, proper names, and descriptive noun phrases.
- The representative must be the most specific mention in the cluster.
- Do not wrap the JSON in markdown fences.
- Do not add commentary outside the JSON."""&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-3-function"&gt;Step 3: Build the resolution function&lt;/h2&gt;

&lt;p&gt;This helper wraps the API call, strips any accidental markdown fences from the output, and parses the result into a native Python dictionary. Dropping temperature to 0.1 keeps the output deterministic.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import json

def resolve_coreference(text: str, model: str = "llama-3.3-70b"):
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": text},
        ],
        temperature=0.1,
    )
    
    raw = response.choices[0].message.content.strip()
    # Guard against models that occasionally return fenced JSON.
    if raw.startswith("

```"):
        raw = raw.split("```

")[1]
        if raw.startswith("json"):
            raw = raw[4:]
    
    return json.loads(raw.strip())&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="step-4-replace"&gt;Step 4: Add a mention replacer&lt;/h2&gt;

&lt;p&gt;To make the resolution visible, I add a small utility that swaps every resolved mention with its representative. It processes longer mentions first so that short pronouns do not clobber substrings inside longer names.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def replace_mentions(text: str, clusters: list):
    """
    Naive exact-match replacement: swaps each mention with the representative.
    Processes longer mentions first to avoid partial overwrites.
    """
    for cluster in clusters:
        rep = cluster["representative"]
        mentions = sorted(cluster["mentions"], key=len, reverse=True)
        for mention in mentions:
            text = text.replace(mention, rep)
    return text&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="run-it"&gt;Run it&lt;/h2&gt;

&lt;p&gt;I will feed the tool a paragraph with multiple people and pronouns, then print the raw clusters and the resolved text. Because Oxlo.ai prices by the request rather than by the token, this call costs the same whether the paragraph is two sentences or two pages. See &lt;a href="https://oxlo.ai/pricing" rel="noopener noreferrer"&gt;https://oxlo.ai/pricing&lt;/a&gt; for plan details.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if __name__ == "__main__":
    paragraph = (
        "Sunita Rao joined the platform team in January. "
        "The backend lead rewrote the auth service, and she cut latency by half. "
        "Marco Diaz took over code review for Sunita. "
        "He merged the branch after he confirmed all edge cases were covered."
    )
    
    result = resolve_coreference(paragraph, model="llama-3.3-70b")
    print(json.dumps(result, indent=2))
    
    resolved = replace_mentions(paragraph, result["clusters"])
    print("\nResolved text:\n" + resolved)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Example output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "clusters": [
    {
      "representative": "Sunita Rao",
      "mentions": ["Sunita Rao", "The backend lead", "she", "Sunita"]
    },
    {
      "representative": "Marco Diaz",
      "mentions": ["Marco Diaz", "He", "he"]
    }
  ]
}

Resolved text:
Sunita Rao joined the platform team in January. Sunita Rao rewrote the auth service, and Sunita Rao cut latency by half. Marco Diaz took over code review for Sunita Rao. Marco Diaz merged the branch after Marco Diaz confirmed all edge cases were covered.&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="next-steps"&gt;Next steps&lt;/h2&gt;

&lt;p&gt;Wire this resolver into an async pipeline so you can process documents in parallel with Oxlo.ai's request-based pricing. For multilingual documents, swap the model to qwen-3-32b or kimi-k2.6 without changing any client code. If you need guaranteed throughput for large backlogs, the Enterprise tier offers dedicated GPUs and custom queue priority.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>oxlo</category>
      <category>ai</category>
    </item>
    <item>
      <title>LLM Models for High-Explainability Tasks: A Comparative Analysis</title>
      <dc:creator>shashank ms</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:32:20 +0000</pubDate>
      <link>https://dev.to/shashank_ms_6a35baa4be138/llm-models-for-high-explainability-tasks-a-comparative-analysis-pkc</link>
      <guid>https://dev.to/shashank_ms_6a35baa4be138/llm-models-for-high-explainability-tasks-a-comparative-analysis-pkc</guid>
      <description>&lt;p&gt;High-explainability tasks require more than accurate predictions. They demand audit trails, reproducible reasoning, and structured outputs that regulators, clinicians, or auditors can inspect. Whether you are generating adverse action notices in lending, annotating medical records, or validating compliance checks, the underlying model must expose its chain of thought and operate reliably across long source documents. This analysis reviews the model traits and infrastructure patterns that make those requirements feasible, and why Oxlo.ai is a practical inference layer for teams that cannot afford black-box responses.&lt;/p&gt;

&lt;h2 id="what-makes-an-llm-explainable"&gt;What Makes an LLM Explainable?&lt;/h2&gt;

&lt;p&gt;Explainability in language models generally breaks down into three operational properties. First, &lt;strong&gt;chain-of-thought visibility&lt;/strong&gt;: the model emits intermediate reasoning steps before a conclusion. Second, &lt;strong&gt;structured generation&lt;/strong&gt;: the output conforms to a predictable schema, such as JSON, so downstream systems can parse justifications and confidence levels. Third, &lt;strong&gt;grounded tool use&lt;/strong&gt;: the model calls external functions or retrieval systems and cites them, creating an observable path from evidence to answer.&lt;/p&gt;

&lt;p&gt;Models that specialize in these behaviors typically ship with large context windows and reasoning-optimized architectures. DeepSeek R1 671B MoE and the Kimi K2.x family are built explicitly for deep chain-of-thought reasoning. Qwen 3 32B adds strong multilingual agent workflows, while GLM 5 handles long-horizon agentic tasks with its 744B MoE architecture. For general-purpose workloads that still require transparent output, Llama 3.3 70B remains a reliable backbone when paired with careful prompting and JSON mode.&lt;/p&gt;

&lt;h2 id="model-categories-for-explainability"&gt;Model Categories for High-Explainability Workloads&lt;/h2&gt;

&lt;p&gt;Not every explainability problem is a chat problem. The right modality depends on whether you are interpreting documents, generating code, or comparing images.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reasoning and chat.&lt;/strong&gt; DeepSeek R1 671B MoE, Kimi K2.6, Kimi K2.5, Kimi K2 Thinking, GLM 5, and Qwen 3 32B dominate tasks that require step-by-step logic. DeepSeek V4 Flash adds a one-million-token context window, which is useful when the audit trail must include entire regulation PDFs or patient histories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code generation.&lt;/strong&gt; Explainable code means traceable logic. Qwen 3 Coder 30B, DeepSeek Coder, and Oxlo.ai Coder Fast are optimized for structured program synthesis where each function boundary is inspectable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vision and document understanding.&lt;/strong&gt; Gemma 3 27B and Kimi VL A3B can extract tables or diagrams and feed them into a reasoning model as structured text, preserving provenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="infrastructure-costs-and-context"&gt;Infrastructure Costs and the Context Window Tax&lt;/h2&gt;

&lt;p&gt;High-explainability workloads are inherently token-hungry. You often ingest full source documents, append detailed system prompts, and request lengthy reasoning traces. Under token-based pricing, which is the standard at providers like Together AI, Fireworks AI, OpenRouter, Replicate, and Anyscale, every paragraph of context and every sentence of explanation adds linear cost. For agentic loops that iterate across multiple tool calls, that tax compounds quickly.&lt;/p&gt;

&lt;p&gt;Oxlo.ai uses request-based pricing: one flat cost per API request regardless of prompt length or output length. For long-context and agentic workloads, this model can be 10-100x cheaper than token-based alternatives because cost does not scale with input length. You can pass an entire regulation corpus or a full medical record into DeepSeek V4 Flash without worrying about per-token metering, and you can ask for exhaustive chain-of-thought reasoning without ballooning your bill. There are no cold starts on popular models, and the platform is fully OpenAI SDK compatible, so switching your base URL is the only code change required. See &lt;a href="https://oxlo.ai/pricing" rel="noopener noreferrer"&gt;https://oxlo.ai/pricing&lt;/a&gt; for plan details.&lt;/p&gt;

&lt;h2 id="implementing-structured-reasoning"&gt;Implementing Structured Reasoning with Oxlo.ai&lt;/h2&gt;

&lt;p&gt;The following Python snippet shows how to call a reasoning model through Oxlo.ai with JSON mode enabled. The goal is a reproducible, machine-readable explanation: the model returns both reasoning steps and a final classification.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import openai
import json

client = openai.OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key="YOUR_OXLO_API_KEY"
)

response = client.chat.completions.create(
    model="deepseek-r1",  # DeepSeek R1 671B MoE
    messages=[
        {
            "role": "system",
            "content": (
                "You are a compliance auditor. Analyze the transaction description. "
                "Respond with valid JSON containing 'risk_factors', 'reasoning_steps', and 'verdict'."
            )
        },
        {
            "role": "user",
            "content": "Wire transfer of $50,000 to offshore holding company with no prior transaction history."
        }
    ],
    response_format={"type": "json_object"},
    temperature=0.1
)

result = json.loads(response.choices[0].message.content)
print(json.dumps(result, indent=2))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because Oxlo.ai is a drop-in replacement for the OpenAI SDK, you keep your existing retry logic, streaming handlers, and function-calling patterns. The difference is that you can now send long regulatory texts or multi-turn agent logs without watching token counters increment. For vision workflows, swap to a vision-capable model such as Gemma 3 27B or Kimi VL A3B and include image URLs in the message payload.&lt;/p&gt;

&lt;h2 id="choosing-the-right-model"&gt;Choosing the Right Model for Your Domain&lt;/h2&gt;

&lt;p&gt;Domain constraints usually dictate which capability matters most.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Healthcare and legal.&lt;/strong&gt; Context is king. DeepSeek V4 Flash offers a one-million-token context window, making it possible to keep an entire case file or discharge summary in the prompt. Kimi K2.6 provides advanced reasoning and agentic coding across 131K tokens. GLM 5 excels at long-horizon agentic tasks where the model must plan over many steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finance and auditing.&lt;/strong&gt; DeepSeek R1 671B MoE delivers deep reasoning for complex numerical logic. Qwen 3 32B handles multilingual regulatory documents, which is critical for cross-border compliance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;General-purpose extraction.&lt;/strong&gt; When you need a balanced workhorse that responds reliably to JSON mode and function calling, Llama 3.3 70B is a strong default on Oxlo.ai.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since Oxlo.ai hosts more than 45 models across seven categories, you can A/B test these options under a single API key and a single pricing framework. There is no need to manage separate accounts at multiple token-based providers to find the best explainer for your data.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Explainability is not a post-processing layer you bolt onto a black box. It is a function of model architecture, context capacity, structured generation support, and inference economics. If your team is building systems where every answer must be traceable, you need models that reason out loud and an infrastructure layer that does not punish you for asking for detail.&lt;/p&gt;

&lt;p&gt;Oxlo.ai removes the per-token penalty for long inputs and lengthy chain-of-thought outputs. With request-based pricing, full OpenAI SDK compatibility, and a broad catalog of reasoning models ranging from DeepSeek R1 to Kimi K2.6, it is a relevant option for any team shipping high-explainability AI into production. Visit &lt;a href="https://oxlo.ai/pricing" rel="noopener noreferrer"&gt;https://oxlo.ai/pricing&lt;/a&gt; to compare plans, or point your existing OpenAI client to &lt;code&gt;https://api.oxlo.ai/v1&lt;/code&gt; to start testing.&lt;/p&gt;

</description>
      <category>aiinfrastructure</category>
      <category>oxlo</category>
      <category>ai</category>
    </item>
    <item>
      <title>Global Trade Dynamics Q3 2026 — Geopolitical &amp; Macroeconomic Analysis</title>
      <dc:creator>Nexus Intelligence Research</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:32:06 +0000</pubDate>
      <link>https://dev.to/rogt7/global-trade-dynamics-q3-2026-geopolitical-macroeconomic-analysis-1g67</link>
      <guid>https://dev.to/rogt7/global-trade-dynamics-q3-2026-geopolitical-macroeconomic-analysis-1g67</guid>
      <description>

&lt;h2&gt;
  
  
  Recommended Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.binance.com/en/register?ref=YOUR_REF" rel="noopener noreferrer"&gt;Binance&lt;/a&gt;&lt;/strong&gt; — Trade crypto with low fees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://shop.ledger.com/pages/ledger-nano-x?r=YOUR_REF" rel="noopener noreferrer"&gt;Ledger&lt;/a&gt;&lt;/strong&gt; — Secure your crypto hardware wallet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://crypto.com/exch/YOUR_REF" rel="noopener noreferrer"&gt;Crypto.com&lt;/a&gt;&lt;/strong&gt; — Buy, sell, and earn crypto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This article was generated by Nexus Intelligence autonomous research system.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>geopolitics</category>
      <category>crypto</category>
      <category>data</category>
    </item>
    <item>
      <title>A 27B London Agent Beat Frontier Models at Reproducing Research</title>
      <dc:creator>AI Tech Connect</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:31:22 +0000</pubDate>
      <link>https://dev.to/rishi_kora/a-27b-london-agent-beat-frontier-models-at-reproducing-research-1j57</link>
      <guid>https://dev.to/rishi_kora/a-27b-london-agent-beat-frontier-models-at-reproducing-research-1j57</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://aitechconnect.in/news/inherent-faraday-27b-replica-benchmark-2026" rel="noopener noreferrer"&gt;AI Tech Connect&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What Inherent shipped On 14 August 2026, Inherent — also referred to as Inherent Labs, a London-based lab founded by Google DeepMind alumni — introduced Faraday, a 27-billion-parameter agent it describes as an “AI Scientist”. The stated purpose is narrower and more interesting than the label suggests: Faraday is built to replicate scientific research, and Inherent positions that capability as a foundation for open-ended discovery rather than an end in itself. Alongside the model, Inherent released the thing that makes the claim legible. Replica is a benchmark of 310 tasks drawn from 100 machine-learning and AI-for-science papers, spanning natural-language processing, materials science and weather forecasting. Each task hands an agent a paper and asks it to reproduce one of the figures —…&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;a href="https://aitechconnect.in/news/inherent-faraday-27b-replica-benchmark-2026" rel="noopener noreferrer"&gt;Read the full article on AI Tech Connect →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>modelrelease</category>
      <category>research</category>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>MCP in practice: building, securing, and serving Model Context Protocol servers</title>
      <dc:creator>Royal Simpson Pinto</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:30:29 +0000</pubDate>
      <link>https://dev.to/royalpinto007/mcp-in-practice-building-securing-and-serving-model-context-protocol-servers-i36</link>
      <guid>https://dev.to/royalpinto007/mcp-in-practice-building-securing-and-serving-model-context-protocol-servers-i36</guid>
      <description>&lt;p&gt;The Model Context Protocol is the plug that connects an AI agent to real capabilities. Instead of every client inventing its own way to call your tools, an MCP server advertises a list of tools, resources, and prompts over a standard JSON-RPC 2.0 interface, and any MCP client (Claude Code, Cursor, an agent built on the Claude Agent SDK) can discover and call them. That standardization is the whole point, and it is also where the danger lives: the moment you expose a tool, you are handing a language model a lever it can pull on your systems. Over three projects I built a server, scoped one down to per-client permissions, and wrote a scanner to catch the mistakes. Here is what actually mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a server: the transport is simpler than it looks
&lt;/h2&gt;

&lt;p&gt;My first server, &lt;strong&gt;casebook-mcp&lt;/strong&gt;, turns AgentPostmortem (a public registry of documented AI-agent failures) into something an agent can query mid-investigation. The idea: every team debugging an agent incident is rediscovering failure modes someone already wrote up. So the server exposes four tools: &lt;code&gt;search_cases&lt;/code&gt; for ranked full-text search, &lt;code&gt;get_case&lt;/code&gt; for full case detail, &lt;code&gt;similar_failures&lt;/code&gt; to match an incident description against the corpus, and &lt;code&gt;list_tags&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The lesson here was that you do not need a heavy framework. I implemented the transport directly against the 2025-03-26 streamable HTTP spec in stateless mode: a single &lt;code&gt;POST /mcp&lt;/code&gt; endpoint that handles &lt;code&gt;initialize&lt;/code&gt;, &lt;code&gt;tools/list&lt;/code&gt;, and &lt;code&gt;tools/call&lt;/code&gt;. No sessions, no Durable Objects, no auth, because the data is public and read-only. It runs on a Cloudflare Worker with the protocol routing in one file, the pure ranking logic in another (unit tested on its own), and a data layer that hits the live agentpostmortem.com API with a five-minute in-memory cache and falls back to a bundled dataset when offline. A light per-IP rate limit of 60 requests per minute keeps it polite. You can smoke test it with a single curl of &lt;code&gt;tools/list&lt;/code&gt;, and add it to Claude Code with one &lt;code&gt;claude mcp add --transport http&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;The separation that paid off: keeping the search and similarity ranking as pure functions meant I could test the interesting logic without standing up the transport at all. MCP protocol handling is boilerplate. Your actual value is in the tool implementations, so isolate them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoping a server: not every client should see every tool
&lt;/h2&gt;

&lt;p&gt;Public read-only data is the easy case. The hard case is a server that fronts a company's real systems. &lt;strong&gt;Bridgekit&lt;/strong&gt; does exactly that: it exposes Shopify, Triple Whale, and Postgres to an AI stack, and three of its four tools are reads (&lt;code&gt;shopify_orders&lt;/code&gt;, &lt;code&gt;triplewhale_metrics&lt;/code&gt;, &lt;code&gt;db_query&lt;/code&gt; against an allowlisted table) while one is a write (&lt;code&gt;shopify_tag_order&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The design decision I care about most is that &lt;strong&gt;scope is enforced at discovery, not just at call time&lt;/strong&gt;. Clients are configured in a secret as JSON, each with a name, a list of allowed tools, and an &lt;code&gt;allowWrite&lt;/code&gt; flag. When a client calls &lt;code&gt;tools/list&lt;/code&gt;, the server only advertises the tools that client is scoped for. A read-only client never even sees the write tool exists. Callers authenticate with a bearer key (or an &lt;code&gt;x-bridgekit-key&lt;/code&gt; header), and every attempt is written to an append-only audit log. When a read-only key tries to call the write tool, the call is denied and the denial is logged.&lt;/p&gt;

&lt;p&gt;Two things I would tell anyone building this kind of server. First, per-client tool filtering matters more than you expect, because an agent that cannot see a tool cannot be prompt-injected into calling it. Reducing the advertised surface is a security control, not just tidiness. Second, make it demoable safely: Bridgekit's read tools return clearly-labelled sample data when upstream credentials are not configured, so you can show the whole flow without wiring it to a live store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scanning a server: assume you got it wrong
&lt;/h2&gt;

&lt;p&gt;After building two servers, I was convinced I would ship a bad tool eventually, and that most people ship them with no security review at all. So I wrote &lt;strong&gt;mcp-audit&lt;/strong&gt;, a scanner and linter for MCP servers. It connects to a server over stdio or HTTP (or lints a static JSON manifest without executing anything, which is what you want for untrusted servers in code review), enumerates every tool, resource, and prompt, and runs 18 rules over that surface.&lt;/p&gt;

&lt;p&gt;The rules cover the failure classes I kept worrying about: arbitrary command or shell execution tools (&lt;code&gt;MCP002&lt;/code&gt;, critical), destructive tools with no confirmation argument (&lt;code&gt;MCP001&lt;/code&gt;), probable prompt-injection text planted in a tool description (&lt;code&gt;MCP020&lt;/code&gt;), secrets or system paths exposed as resources like a &lt;code&gt;.env&lt;/code&gt; file (&lt;code&gt;MCP030&lt;/code&gt;, critical), caller-controlled URL arguments that invite SSRF (&lt;code&gt;MCP041&lt;/code&gt;), HTTP transport with no authentication (&lt;code&gt;MCP040&lt;/code&gt;), and unconstrained input schemas that let the model pass anything anywhere. Each finding has a stable &lt;code&gt;MCPxxx&lt;/code&gt; id, a severity, and a concrete remediation.&lt;/p&gt;

&lt;p&gt;It is built for CI. It runs offline, is fully deterministic, and emits JSON and SARIF 2.1.0 so findings show up as annotations in GitHub code scanning. The process exits non-zero when any finding reaches the &lt;code&gt;--fail-on&lt;/code&gt; threshold (default &lt;code&gt;high&lt;/code&gt;), so a bad audit breaks the build. You can disable noisy rules, remap severities, or ignore specific locations through a &lt;code&gt;.mcpauditrc&lt;/code&gt; file. Running it against my own servers is what turned "I think this is fine" into "the scanner agrees this is fine."&lt;/p&gt;

&lt;h2&gt;
  
  
  One honest caveat
&lt;/h2&gt;

&lt;p&gt;mcp-audit is a static and structural analyzer. It reasons about the shape of your tools: their names, descriptions, and input schemas. It flags a tool named &lt;code&gt;run_shell&lt;/code&gt; and a resource pointing at &lt;code&gt;.env&lt;/code&gt;, but it cannot know that your innocently named &lt;code&gt;update_record&lt;/code&gt; tool quietly runs raw SQL under the hood, because it never sees the implementation. Pattern-matching on descriptions also means it can miss a cleverly worded injection sink or flag a benign one. It narrows the surface an attacker can reach and catches the obvious, dangerous defaults, but it is a first line of defense, not a substitute for reading the code behind each tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The through-line
&lt;/h2&gt;

&lt;p&gt;Building the transport is the least of it. The work that matters is deciding which tools exist, who is allowed to see them, and proving to yourself that none of them are a foot-gun before an agent finds out for you. All three projects are open source under &lt;a href="https://github.com/royalpinto007" rel="noopener noreferrer"&gt;github.com/royalpinto007&lt;/a&gt;: casebook-mcp, Bridgekit, and mcp-audit. If you are shipping an MCP server, at minimum run a scanner over it first.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
