Tutorial: Agent Trust Kits
Build a bounded agent-to-tool trust flow using capability SD-JWTs.
Time: 25 minutes
Level: Intermediate
Sample: samples/SdJwt.Net.Samples/02-Intermediate/06-AgentTrustKits.cs
What You Will Learn
- How to mint capability tokens for tool calls
- How to enforce policy-based allow/deny decisions
- How to verify capability tokens in ASP.NET Core
- How MAF middleware and MCP adapter fit into the flow
Step 1: Install Packages
dotnet add package SdJwt.Net.AgentTrust.Core
dotnet add package SdJwt.Net.AgentTrust.Policy
dotnet add package SdJwt.Net.AgentTrust.AspNetCore
dotnet add package SdJwt.Net.AgentTrust.Maf
Step 2: Define Policy Rules
using SdJwt.Net.AgentTrust.Core;
using SdJwt.Net.AgentTrust.Policy;
var rules = new PolicyBuilder()
.Deny("*", "billing", "Delete")
.Allow("agent://finance-*", "billing", "Read", c =>
{
c.MaxLifetime(TimeSpan.FromSeconds(60));
c.Limits(new CapabilityLimits { MaxResults = 50 });
})
.Build();
var policyEngine = new DefaultPolicyEngine(rules);
Step 3: Mint a Capability Token
using Microsoft.IdentityModel.Tokens;
using SdJwt.Net.AgentTrust.Core;
using SdJwt.Net.AgentTrust.Maf;
using System.Security.Cryptography;
var signingKey = new SymmetricSecurityKey(RandomNumberGenerator.GetBytes(32));
var nonceStore = new MemoryNonceStore();
var issuer = new CapabilityTokenIssuer(
signingKey,
SecurityAlgorithms.HmacSha256,
nonceStore);
var adapter = new McpTrustAdapter(
issuer,
policyEngine,
"agent://finance-eu",
new Dictionary<string, string> { ["billing"] = "https://tools.example.com" });
var tokenResult = await adapter.MintForToolCallAsync(
"billing",
new Dictionary<string, object> { ["action"] = "Read" },
new CapabilityContext { CorrelationId = Guid.NewGuid().ToString("N") });
Step 4: Verify in ASP.NET Core Tool API
using Microsoft.IdentityModel.Tokens;
using SdJwt.Net.AgentTrust.AspNetCore;
builder.Services.AddAgentTrustVerification(options =>
{
options.Audience = "https://tools.example.com";
options.TrustedIssuers = new Dictionary<string, SecurityKey>
{
["agent://finance-eu"] = signingKey
};
});
app.UseAgentTrustVerification();
Protect endpoint:
[RequireCapability("billing", "Read")]
[HttpGet("invoices/{id}")]
public IActionResult GetInvoice(string id) => Ok();
Step 5: Send Request with Token
Set request header:
Authorization: SdJwt <tokenResult.Token>
If verification and policy checks pass, the request continues to your endpoint.
Run the runnable sample:
cd samples/SdJwt.Net.Samples
dotnet run -- 2.6
Troubleshooting
401 Unauthorized: missing or malformed header/token.403 Forbidden: token invalid, expired, or policy denied.- Replay rejection: same token reused with replay prevention enabled.
- Audience mismatch:
auddoes not equal configuredoptions.Audience.