Download audio: https://www.directionsonmicrosoft.com/wp-content/uploads/2026/09/season5ep14atlasai.mp3
This week, Mistral announced it raised €3 billion in a Series D funding round, pushing its post-money valuation past €21 billion. With the influx of cash — $3.5 billion in US dollars — it plans to expand its frontier research, scale compute capacity for model training, and grow its infrastructure.
Where Mistral’s allocating new funds suggests what the French AI company is betting on for the future of AI power: open-weight models can only do so much if the compute and infrastructure underneath remain concentrated among a few key players.
So far, model superiority has been a major factor in who gets to rule the AI roost. Some open-weight advocates have been touting open-weight models as a way to combat this concentration by giving developers more choice over the models they use — and a way to escape dependence on proprietary APIs. This way, rather than relying exclusively on one provider’s model, developers can adapt open-weight models for their own use.
The catch? Running powerful models takes enormous amounts of compute. Training frontier models — and serving them at high volume — requires compute capacity concentrated among a relatively small number of labs, chip suppliers, and infrastructure providers.
For his part, Dario Amodei, CEO and co-founder of Anthropic, challenged that vision for open-weight models last month in an exchange on X, where he wrote that open weights “are nowhere near a sufficient solution because they simply shift the concentration somewhat to those with the most compute and chips.”
But the expansion plans Mistral briefly outlines in its funding news suggest there’s a different way to combat that dominance: Don’t stop at opening the model. Build more of the stack, instead.
“Mistral is the only AI company in the world building the full stack required to answer that question,” claims the French AI company, writing about how organizations can take advantage of AI for mission-critical needs without giving up control of the infrastructure and intelligence loop.
For Mistral, building that stack means developing open-weight models and the infrastructure and compute capacity on which those models run, along with the downstream products that bring them into production. And with a new €3B in the bank — led by Samsung Electronics, with Scaleup Europe Fund, managed by EQT, and existing investor PSG Equity as co-leads — parts of that stack will keep expanding.
Looking ahead, Mistral says it aims to use its full stack and open approach to AI to free customers from dependence on a single vendor’s roadmap, pricing, and availability so they can build on its stack “without exposing their most valuable data, workflows and institutional knowledge to anyone outside their walls.”
That addresses one piece of Amodei’s critique of open-weight models. Because Mistral’s stack includes not only the models but also the compute, infrastructure, and production layer, its open-weight strategy depends less on rival-controlled infrastructure.
Launched three years ago, Mistral has made a name for itself by releasing open-weight models. Interestingly, it’s also been expanding into the infrastructure layer as of late.
Last month, the company said it would begin hosting third-party open models, putting the likes of GLM-5.2 from China’s Z.ai on the same infrastructure as its own models — another move that suggests it sees the infrastructure layer as an increasingly important part of the AI race.
In July, Arthur Mensch, co-founder and CEO, Mistral, added to the case for more openness by taking to LinkedIn to express his concerns about dependence on closed-model providers, writing:
“Of course you need to use open-source models if you’re an enterprise leader. Closed-model providers, that are now forcing data retention, are gaining immense leverage on your business if you don’t.”
Bigger picture, it looks like Mistral’s betting that whoever ends up ruling the AI roost will need more than the best-performing model; they’ll also need to control enough of the surrounding infrastructure to give customers choices about which models they want to use and on what infrastructure.
Whether this can meaningfully shift AI power, though, remains to be seen.
The post Mistral wants open-weight AI to compete at the frontier. It just raised $3.5 billion to do it. appeared first on The New Stack.
When several Visual Studio instances are open, identifying the right one becomes a surprisingly repetitive task. Two windows showing different checkouts of the same solution can look almost identical. Reading the title works, but a small visual cue is easier to spot.
That's the problem behind Solution Colors. Inspired by the Peacock extension for VS Code and a Visual Studio feature request, it associates a color with a solution or folder without replacing your editor theme.

Right-click the solution in Solution Explorer, choose Set Solution Color, and select a color. The predefined choices use the familiar document-tab color palette, and Custom... opens a color picker when you want something different. Open Folder workspaces are supported too.

The color can appear around the window, behind the solution name in the title bar, and in taskbar thumbnails. Taskbar icon overlays are also available, with the documented limitation that taskbar items need to be ungrouped. You can choose the surfaces that help you and leave the others alone.
Under Tools > Options > Environment > Fonts and Colors > Solution Colors, you can adjust border placement and thickness or enable automatic color assignment. Automatic mode selects from the palette using a hash of the solution path; explicitly saved colors take precedence.
The project is an in-process VSIX built with the Visual Studio SDK and the Community Toolkit. Its ToolkitPackage registers commands and listens for solution and folder open/close events. The menu lives in a VSCT command table, while the color commands share a generic BaseCommand<T> implementation.
That is the conventional part. Coloring the existing window chrome is less conventional.
The implementation searches the WPF visual tree for named shell elements such as BottomDockBorder and PART_SolutionNameTextBlock. It changes brushes and border thickness rather than introducing a new tool window. For the title label, it also uses reflection to access the foreground property and Visual Studio's ColorUtilities.CompareContrastWithBlackAndWhite to choose black or white text.
This is an important tradeoff for extension authors: finding an element in the shell's visual tree is not the same as having a dedicated, stable extensibility contract for it. Names and structure can change. The lookup code is worth isolating, and these integrations need testing against the Visual Studio versions you support.
One revealing detail is hit testing. The extension disables hit testing on the non-top borders it colors so they don't intercept mouse input. But it deliberately leaves the top element alone: MainWindowTitleBar contains interactive UI, and disabling hit testing there would also block menu interaction.
That distinction is easy to overlook when the feature appears to be "just a border." Decorative changes still participate in layout and input routing.
Timing matters too. Package initialization does not guarantee that every shell element is ready. The startup path makes a bounded series of colorization attempts, with delays between them. UI changes switch to the main thread, while Git branch file reads are dispatched to a background task.
Taskbar integration uses a different mechanism: WPF's TaskbarItemInfo, noninteractive ThumbButtonInfo entries, and an overlay image. There is no need to reach into the taskbar's visual tree.
The settings offer one color across branches, a separate color per branch, or a combined gradient. Assignments are stored as simple branch:color lines in a color.txt file, normally under the solution's .vs directory. An option puts the file in the root instead. The parser also accepts the older single-color format.
There is a compatibility detail worth knowing: the implementation uses the literal key master for its shared/base color. That is an internal convention, not automatic discovery of a repository's configured default branch.
A recent fix illustrates why separating decisions from rendering helps. In per-branch mode, a branch with an explicit color should remain colored even when no base color has been assigned. The code now expresses the removal decision in ShouldRemoveColorization, with focused unit tests covering the different modes and automatic-color behavior.
That is a useful pattern beyond this extension: put the state rules in a testable method, then let the UI code apply the result. You shouldn't need to launch an experimental Visual Studio instance just to verify whether a missing base setting overrides a branch-specific one.
If you regularly juggle Visual Studio windows, install Solution Colors from the Marketplace and give your solutions a visual identity.
If you're building extensions, browse the source on GitHub. Start with SolutionColorsPackage for the lifecycle, ColorHelper for the shell integration, and the tests for the branch-color rules. A few pixels of color turn out to be a useful case study in extending the IDE without getting in the user's way.

For over two decades, the API Gateway has been one of the most important pieces of modern application architecture. Whether you’re building a mobile application, a SaaS platform, or a collection of microservices, chances are every request from your users passes through an API Gateway before it reaches your backend.
But something has changed.
The clients making requests are no longer just browsers and mobile apps. Increasingly, they’re AI agents, and AI agents behave very differently from traditional software. As a result, we are beginning to see the emergence of a new architectural component called the Agent Gateway.
To understand why it is needed, it helps to trace how gateways have evolved.
When I think about gateways in software, the first concept that comes to mind is a proxy.
A proxy is an intermediary between two systems. A forward proxy acts on behalf of a client, while a reverse proxy sits in front of one or more servers and acts on their behalf.
At its core, an API Gateway is a reverse proxy with capabilities designed specifically for managing APIs. That may sound like an oversimplification, but it is a useful mental model.
An API Gateway sits between API consumers and the services that fulfill their requests.
Imagine a user opening a food-delivery application and tapping Order food. The application sends a request through an API Gateway, which routes it to the appropriate backend services.

The gateway may handle routing and load balancing, authentication and authorization, rate limiting and quotas, TLS termination, Protocol translation, Request and response transformation, Caching, Logging, tracing, and observability, API versioning and lifecycle policies and many more.
Most importantly, the API Gateway makes a fundamental assumption about its client:
The client already knows which API it wants to call.
A mobile app doesn’t ask “How do I order food?”. Its developers have already encoded that logic into the application. The client knows that it needs to send a request such as:
The API Gateway’s job is to authenticate, govern, route, and reliably deliver that request at scale.
Now imagine replacing that mobile app with an AI agent. Instead of receiving a predetermined instruction to call a specific endpoint, the agent receives a goal. “Book me a hotel near the conference venue under $250.”
To accomplish this, the agent might need to:
The exact sequence is not necessarily known in advance. It may change depending on the information returned by each tool, but the agent must repeatedly decide:
This is fundamentally different from traditional applications. Instead of executing workflows that developers have already mapped out. An AI agent determines parts of the workflow dynamically at runtime. That flexibility is what makes agents powerful. It is also what makes them difficult to control.
As large language models became widely adopted, organizations encountered a new set of production concerns. Applications were no longer calling only conventional APIs. They were also sending prompts to multiple model providers, receiving probabilistic outputs, consuming tokens, and incurring variable costs.
This led to the emergence of the LLM Gateway, sometimes called an AI Gateway.
An LLM Gateway applies familiar gateway patterns to model inference traffic. It can centralize capabilities such as:
For example, an LLM Gateway might route simple classification requests to a smaller, less expensive model while sending complex reasoning tasks to a more capable one. It might switch providers when a model is unavailable, enforce a team’s monthly budget, or redact sensitive information before a prompt leaves the organization.
These are important production capabilities, but the primary object being managed is still the model request.

An LLM Gateway helps an application use models reliably, securely, and cost-effectively.
An agent, however, depends on much more than a model.
Anthropic introduced the Model Context Protocol, or MCP, in November 2024 as an open standard for connecting AI applications to external tools and data sources. Since then, MCP has become an important part of the agentic ecosystem.
Instead of creating a proprietary integration for every agent and every external system, developers can expose capabilities through MCP servers. An agent can then use those servers to search a database, retrieve a document, create an issue, send a message, query an API, or perform another action.

However, standardizing the protocol does not automatically solve the operational problems involved in managing a large tool ecosystem.
Different MCP servers may represent different security boundaries. They may depend on separate authorization servers, credentials, scopes, network policies, and downstream APIs. One MCP server may use an API key for authentication, while another uses OAuth 2.0, and another OAuth 2.1 + DCR. This makes centrally managing auth difficult. The MCP specification recommends OAuth-based mechanisms, but deployment models and implementation maturity can still vary across servers and a lot of MCP servers today are not fully complaint with the spec.
As organizations connect agents to tens or hundreds of tools, several challenges emerge:
The final problem is particularly important. Tool definitions and tool results consume context. As the number of available tools grows, blindly exposing all of them to the model can increase token consumption, latency, and the likelihood that the model selects the wrong tool. Tool discovery and selective loading therefore become operational concerns, not merely prompt-engineering concerns.
An MCP Gateway provides a centralized control point between MCP clients and MCP servers.

Depending on the implementation, it can provide:
The MCP Gateway governs access to MCP-based capabilities. But MCP servers are still only one part of an agentic system.
An AI agent may depend on some or all of the following:
An Agent Gateway is an intelligent middleman between an AI Agent, and all the components it relies on. Agent Gateways provide a centralized control plane and enforcement point across these interactions. These can include, LLMs, MCP Tools, Memory, other Agents, and of course, an API.

Like an API Gateway, an Agent Gateway may proxy requests, enforce access controls, apply policies, limit traffic, and collect telemetry.
Like an LLM Gateway, it may govern model selection, token usage, prompts, responses, safety controls, and cost.
Like an MCP Gateway, it may manage tool discovery, credentials, permissions, and tool invocation.

But its scope is broader than any one of those categories. It governs the agent’s interactions as part of a complete runtime workflow.
An Agent Gateway may be responsible for:

Traditional API security is usually based on a relatively clear identity chain.
A user authenticates to an application. The application receives a token. The token identifies the user, the application, or both. Backend services validate that identity and enforce the corresponding permissions.
Agents complicate this model. An agent may be acting on behalf of a user, running as an independent workload, invoked by another agent, operating across multiple sessions, delegating work to subagents, using shared infrastructure, or even calling tools that require different identities.
When an agent invokes a tool, which identity should the tool evaluate? Is it the identity of the user, the application, the agent, or the organization? What happens when one agent delegates a task to another? Which permissions should be transferred, and for how long?
Without a consistent identity and delegation model, systems tend to fall back to shared API keys or overly broad service accounts. That makes least-privilege authorization difficult and weakens accountability.
An Agent Gateway can provide a consistent point for establishing agent identity, propagating user context, exchanging credentials, narrowing scopes, and recording who or what initiated each action.
A traditional chatbot primarily generates text. An agent can generate text and then use that text to take action. It may send an email, modify source code, issue a refund, retrieve customer records, deploy an application, or initiate a payment.
This creates risks that do not exist in an ordinary API traffic:
Authentication alone does not solve these problems. A request can be properly authenticated and still be unsafe. Agentic systems need policies that evaluate more than the caller and endpoint. They may need to consider the user’s intent, the selected tool, the arguments, the current workflow state, the sensitivity of the resource, and the potential consequence of the action.
An Agent Gateway can enforce controls at these boundaries. For example, it might allow an agent to search financial transactions but require human approval before issuing a refund.
An individual LLM request is generally stateless i.e the model receives an input and produces an output.
An agentic workflow is stateful and may maintain conversation history, a task plan, previous tool results, user preferences, intermediate artifacts, approval status, retry counts, budget consumed, and long-term memories.
This does not mean the gateway itself must store all agent memory. In many architectures, memory will remain in dedicated databases, vector stores, or state-management services. The gateway’s role is to govern access to that state.
It can determine which agent may read or write a memory, what context may be sent to a model, which information must be redacted, and whether state from one user or session can be reused in another. This distinction matters. An Agent Gateway does not need to become the memory database.
It needs to become the policy and visibility layer through which memory is accessed.
API observability typically focuses on individual requests, such as which endpoint was called, how long it took, what status code was returned, and which service handled the request.
LLM observability adds another set of questions, including which model was used, how many tokens were consumed, what the request cost, and whether a guardrail was triggered. Agentic observability must connect all of these events into a coherent execution trace.
For a single user request, an agent might make several model calls, invoke multiple tools, query memory, delegate to another agent, retry failed operations, and wait for human approval.
When the final result is wrong, it is not enough to know that one API returned a 200 OK; you need to understand the goal the agent received, the plan it formed, the tools available, why it selected a particular tool, which arguments it generated, what the tool returned, how that result affected the next decision, where time and tokens were spent, which policy decisions were applied, which user, agent, and credential were involved, and where the workflow failed.
An Agent Gateway can capture these interactions at a shared boundary and correlate them into an end-to-end trace.
A traditional application usually has bounded execution paths, but an agent can keep planning, calling tools, evaluating results, and retrying until it reaches a stopping condition. Without clear limits, this can lead to long or infinite loops, repeated tool calls, runaway token usage, escalating costs, duplicate side effects, cascading agent-to-agent delegation, and repeated failed authentication attempts.
Conventional request-per-second limits are not enough for agentic systems. They need controls that account for the full workflow, including token and cost budgets, tool-call volume, delegation depth, execution time, retries, concurrency, and the sensitivity of the requested operation.
The Agent Gateway can enforce these limits across the entire execution, rather than evaluating each request in isolation.
API Gateways were designed for a world in which applications knew which endpoints to call.
LLM Gateways emerged when model inference introduced new routing, cost, privacy, and safety requirements.
MCP Gateways emerged as agents gained access to a growing ecosystem of tools and context providers.
Agent Gateways are the next step in that evolution.
They are needed because the unit being governed is no longer only an API request, a model invocation, or a tool call. It is an agentic execution, a sequence of decisions and actions taken dynamically to achieve a goal. That shift alone changes the role of the gateway.
The gateway is no longer concerned only with:
Is this client allowed to call this endpoint?
It must also help answer:
Is this agent allowed to take this action, with this tool, using this identity, in this context, at this point in the workflow?
APIs are not disappearing. They remain the foundation on which agents act, but the clients consuming them are changing. They can reason, choose tools, delegate work, maintain state, and take consequential actions.
As clients evolve, the gateway must evolve with them.
At Postman, we are building what we believe is the next generation of this architecture, we call it the Fabric Gateway.
Fabric Gateway is designed to bring together the capabilities discussed in this article – API governance, model routing, MCP tool management, and agent-level policy enforcement, into a unified control plane for agentic systems.
Our goal is simple: make it possible to safely run agents in production without sacrificing flexibility, speed, or developer experience.
We are currently opening up early access to teams that are building agentic applications and want to help shape this new category.
If you are exploring agents in production, or thinking about how to govern them at scale, we would love to hear from you.
Join the early access and help define what the Agent Gateway should become.
The post Agent Gateway: The Next Evolution of the API Gateway appeared first on Postman Blog.
tl;dr
Imagine an AI assistant in your company that can write emails, check expense reports, and run CI pipeline steps — but it has every capability baked into one giant prompt. It’s slow, expensive, brittle, and dangerously able to access systems it shouldn’t. Now imagine the same assistant composed from many small, well-documented, auditable “skills”: a policy-checker skill for expenses, an email-composer skill, a CI-invoker skill. Each skill advertises a compact summary the agent sees up-front and provides richer instructions or safe code only when needed. That’s the difference agent skills make: modularity, safety, and maintainability.

In this post you’ll get:
What are agent skills?
A skill is a small, focused package that gives an AI agent a specific capability. A skill typically contains:
Why skills matter
SKILL.md: the portable skill package
A commonly adopted pattern is a small folder that contains a single SKILL.md file (YAML or structured text) that describes the skill plus optional prompt, code and example files. This single file is how registries, marketplaces and agent orchestrators discover and reason about a skill.
A minimal skill folder:
Example SKILL.md (YAML-like):
name: Document Summarizer
summary: Summarize documents into a single short paragraph.
description: |
The Document Summarizer skill produces a concise, factual paragraph that preserves
key facts and avoids hallucination. Use it for internal reports and documentation.
inputs:
Two broad kinds of functions inside skills
How agents use skills (discovery → execution)
C# approach: two patterns
Runnable sample: a small console app that demonstrates semantic and native skills
This sample is framework-agnostic and uses HTTP calls to a standard LLM API (OpenAI-style). Files provided:
Project file: AgentSkillsSample.csproj
Exe net7.0 latest
Notes: YamlDotNet reads SKILL.md, Serilog logs audit events, Newtonsoft.Json serializes HTTP payloads. You can substitute other libs (System.Text.Json) if you prefer.
Note: This code was generated by Copilot and has not been fully tested. Caveat Programmer!
using System.Collections.Generic;
public class SkillDefinition
{
public string Name { get; set; }
public string Summary { get; set; }
public string Description { get; set; }
public List<SkillIO> Inputs { get; set; } = new();
public List<SkillIO> Outputs { get; set; } = new();
public List<PromptFile> Prompts { get; set; } = new();
}
public class SkillIO
{
public string Name { get; set; }
public string Type { get; set; }
public string Description { get; set; }
}
public class PromptFile
{
public string File { get; set; }
}
Skill loader: SkillLoader.cs
using System;
using System.IO;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
public static class SkillLoader
{
// Loads SKILL.md (YAML) and returns SkillDefinition; progressive disclosure: never load prompt files here
public static SkillDefinition LoadSkillMetadata(string skillFolder)
{
var path = Path.Combine(skillFolder, "SKILL.md");
if (!File.Exists(path)) throw new FileNotFoundException("SKILL.md not found", path);
var yaml = File.ReadAllText(path);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var def = deserializer.Deserialize<SkillDefinition>(yaml);
return def;
}
// Load a prompt file only when invoked
public static string LoadPrompt(string skillFolder, string promptFile)
{
var path = Path.Combine(skillFolder, promptFile);
return File.Exists(path) ? File.ReadAllText(path) : throw new FileNotFoundException(promptFile);
}
}
using System;
[AttributeUsage(AttributeTargets.Method)]
public class SkillFunctionAttribute : Attribute
{
public string Name { get; set; }
public SkillFunctionAttribute(string name = null) { Name = name; }
}
using System.Threading.Tasks;
public class FinanceSkill
{
[SkillFunction("GetExchangeRate")]
public Task GetExchangeRateAsync(string currency)
{
// Replace with real API call; this is a stub for demo
return Task.FromResult(currency.ToUpper() switch
{
"EUR" => "1 USD = 0.92 EUR",
"JPY" => "1 USD = 150 JPY",
_ => "1 USD = 1 UNKNOWN"
});
}
}
Native skill attribute and example: Skills/SkillFunctionAttribute.cs and Skills/FinanceSkill.cs
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Serilog;
class Program
{
static readonly string OPENAI_API_KEY = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
static readonly HttpClient http = new HttpClient();
static async Task Main()
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
if (string.IsNullOrEmpty(OPENAI_API_KEY))
{
Console.WriteLine("Set OPENAI_API_KEY environment variable.");
return;
}
// 1. Discover skills (metadata only)
var skillFolder = Path.Combine(Directory.GetCurrentDirectory(), "Skills", "DocumentSummarizer");
var meta = SkillLoader.LoadSkillMetadata(skillFolder);
Console.WriteLine($"Discovered skill: {meta.Name} - {meta.Summary}");
// 2. Example: call semantic (prompt) function (progressive disclosure: load prompt on demand)
var promptTemplate = SkillLoader.LoadPrompt(skillFolder, meta.Prompts.First().File);
var inputText = File.ReadAllText(Path.Combine(skillFolder, "examples", "example1.txt"));
var prompt = promptTemplate.Replace("{{input}}", inputText);
Console.WriteLine("Calling LLM for summary...");
var summary = await CallChatCompletionAsync(prompt);
Console.WriteLine("Summary:\n" + summary);
Log.Information("SkillInvocation: {@skill} {@inputLength}", meta.Name, inputText.Length);
// 3. Example: call native skill directly via reflection
var finance = new FinanceSkill();
var method = typeof(FinanceSkill).GetMethods()
.FirstOrDefault(m => m.GetCustomAttributes(false).Any(a => a.GetType().Name == "SkillFunctionAttribute"));
if (method != null)
{
var resultTask = (Task<string>)method.Invoke(finance, new object[] { "EUR" });
var rate = await resultTask;
Console.WriteLine("Exchange rate (from native skill): " + rate);
Log.Information("NativeSkillInvocation: {@skill}", "Finance:GetExchangeRate");
}
}
// Minimal OpenAI Chat Completion HTTP call (simple completion flow). Adjust model as desired.
static async Task<string> CallChatCompletionAsync(string prompt)
{
var request = new
{
model = "gpt-4o-mini",
messages = new[] { new { role = "user", content = prompt } },
max_tokens = 400
};
var req = new HttpRequestMessage(HttpMethod.Post, "https://api.openai.com/v1/chat/completions");
req.Headers.Add("Authorization", $"Bearer {OPENAI_API_KEY}");
req.Content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var resp = await http.SendAsync(req);
resp.EnsureSuccessStatusCode();
var json = await resp.Content.ReadAsStringAsync();
dynamic data = JsonConvert.DeserializeObject<dynamic>(json);
// Extract the assistant content safely
var text = (string)data.choices[0].message.content;
return text.Trim();
}
How this demonstrates key patterns
RAG + embeddings: a minimal in-memory example
Real RAG pipelines use a vector DB (Pinecone, Weaviate, FAISS) and an embedding endpoint. For a compact demo we’ll:
Embedding call (OpenAI-style)
static async Task GetEmbeddingAsync(string text)
{
var request = new { model = "text-embedding-3-small", input = text };
var req = new HttpRequestMessage(HttpMethod.Post, "https://api.openai.com/v1/embeddings");
req.Headers.Add("Authorization", $"Bearer {OPENAI_API_KEY}");
req.Content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var resp = await http.SendAsync(req);
resp.EnsureSuccessStatusCode();
dynamic data = JsonConvert.DeserializeObject(await resp.Content.ReadAsStringAsync());
var vector = data.data[0].embedding.ToObject();
return vector;
}
Simple in-memory vector store (pseudo code)
RAG flow (high level)
Operational concerns: security, governance, and robustness
Skills are powerful and potentially dangerous. Here are concrete controls and practices.
1) Least privilege for native skills
2) Runtime isolation & sandboxing
3) Audit logging
4) Approval & registry
5) Limit function-calling from LLM
Testing & CI for skills
Treat skills like code: add unit tests, integration tests and CI gates.
1) Unit tests
Example xUnit test for FinanceSkill
[Fact]
public async Task GetExchangeRate_ReturnsExpected()
{
var svc = new FinanceSkill();
var res = await svc.GetExchangeRateAsync(“EUR”);
Assert.Contains(“EUR”, res);
}
2) Integration tests
3) CI pipeline (GitHub Actions example)
name: CI
on: [push, pull_request]
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-dotnet@v4
with:
dotnet-version: 7.0.x
– run: dotnet restore
– run: dotnet build –configuration Release –no-restore
– run: dotnet test –no-build –verbosity normal
Add a step for SKILL.md schema validation (use a small script that parses SKILL.md using YamlDotNet and fails CI for missing fields).
Observability & telemetry
Resilience patterns
Advanced patterns and mapping to SDKs
Common failure modes and mitigations
1) Hallucinations / incorrect output
When to use semantic vs native skills
Packaging and governance checklist
Key takeaways