C# SDK
Vadyl.ClientInstall
dotnet add package Vadyl.ClientInstall-Package Vadyl.Clientpaket add Vadyl.ClientCreate the client
Configure the client once. Same object reaches every product surface — entities, workflows, agents, realtime.
using Vadyl.Client;
var vadyl = new VadylClient(new VadylClientOptions
{
ApiUrl = "https://api.vadyl.app/v1",
Token = Environment.GetEnvironmentVariable("VADYL_TOKEN"),
Tenant = "acme",
Project = "billing",
// optional — pin to a feature branch
Branch = Environment.GetEnvironmentVariable("VADYL_BRANCH"),
});
// Or with DI:
// services.AddVadylClient(opts => { opts.ApiUrl = "..."; ... });
// IVadylClient vadyl = sp.GetRequiredService<IVadylClient>();List, filter, paginate
Typed filter expressions, cursor pagination, eager relation loading.
// Typed filter, sort, pagination, and relation expansion
var recent = await vadyl.Orders.ListAsync(new ListOrderRequest
{
Filter = new OrderFilter
{
Status = OrderStatus.Paid | OrderStatus.Fulfilled,
Total = OrderFilter.Gt(100m),
CreatedAt = OrderFilter.SinceNow("-30d"),
},
Sort = [new Sort("createdAt", SortDir.Desc)],
PageSize = 50,
Include = ["customer", "items.product"],
});
// recent.Data: IReadOnlyList<Order>
// recent.Page: { Number, Size, TotalCount?, Next?, Prev? }
Console.WriteLine($"{recent.Data.Count} orders, next: {recent.Page.Next}");Create, update, delete with idempotency
Every mutation supports idempotency keys. Retries are safe by default.
// Idempotent create — safe to retry
var customer = await vadyl.Customers.CreateAsync(
new CustomerCreateInput { Email = "ada@example.com", Name = "Ada Lovelace" },
idempotencyKey: $"signup:{session.Id}");
// Update with optimistic concurrency
var updated = await vadyl.Customers.UpdateAsync(
customer.Id,
new CustomerUpdateInput { Name = "Ada L." },
ifMatch: customer.ConcurrencyToken);
// Delete (soft-delete on entities with that lifecycle)
await vadyl.Customers.DeleteAsync(customer.Id);Subscribe to entity changes
Field names only — never values. Re-read for values through CRUD with proper access enforcement.
// IAsyncEnumerable streaming subscription with the same filter AST as queries
await foreach (var evt in vadyl.Orders
.Subscribe(
new OrderFilter { Status = OrderStatus.Paid },
kinds: [ChangeKind.Created, ChangeKind.Updated])
.ReadAllAsync(ct))
{
// evt.Kind, evt.EntityId, evt.ChangedFields, evt.OccurredAt
// Field NAMES only — re-read for values
var order = await vadyl.Orders.ReadAsync(evt.EntityId, ct);
Console.WriteLine($"paid: {order.Id}");
}Start and signal durable workflows
Long-running product behavior that survives process restart. Same client interface; canonical durability underneath.
// Start a durable workflow
var run = await vadyl.Workflows.FulfillOrder.StartAsync(
new FulfillOrderInput { OrderId = "ord_abc" });
// Send a signal (e.g. from a webhook)
await vadyl.Workflows.FulfillOrder.SignalAsync(
run.Id,
"shipped",
new { TrackingNumber = "1Z..." });
// Query run state
var state = await vadyl.Workflows.FulfillOrder.QueryAsync(run.Id);Run agents against the product model
Typed plan IR, capability-aware model routing, token accounting — all behind one method.
// Run an agent — typed plan IR, capability-aware model routing
var run = await vadyl.Agents.SupportAgent.RunAsync(new AgentRunInput
{
Prompt = "Refund order #12345 due to defect",
UserId = session.UserId,
Budget = new AgentBudget { MaxTokens = 50_000, MaxToolCalls = 30 },
});
// Stream the run
await foreach (var step in run.StreamAsync(ct))
Console.WriteLine($"{step.Kind}: {step.Summary}");
// Recall memory
var facts = await vadyl.Agents.SupportAgent.Memory.RecallAsync(new RecallRequest
{
Kind = "preference",
Subject = session.UserId,
});Typed error contract
Stable error codes, stable reason codes, correlation IDs, and explainability links.
try
{
await vadyl.Orders.UpdateAsync(id, new OrderUpdateInput { Status = OrderStatus.Refunded });
}
catch (VadylAccessDeniedException ex)
{
Console.WriteLine($"{ex.ReasonCode} ({ex.CorrelationId})");
}
catch (VadylConflictException)
{
// optimistic-concurrency mismatch — re-read and retry
}
catch (VadylValidationException ex)
{
foreach (var e in ex.FieldErrors) Console.WriteLine($"{e.Field}: {e.ReasonCode}");
}
catch (VadylException ex)
{
Console.WriteLine($"{ex.Code}: {ex.Message}");
}Define handlers, workflows, agents
The same package you use as a client also powers your authored runtime — defineCoreHandler, defineWorkflow, defineAgent.
using Vadyl.Authoring;
public class ChargeOrderHandler : ICoreHandler<ChargeInput, ChargeResult>
{
public async Task<ChargeResult> InvokeAsync(IRuntimeContext ctx, ChargeInput input, CancellationToken ct)
{
var order = await ctx.Entities.Order.ReadAsync(input.OrderId, ct);
var charge = await ctx.Connections.Stripe.CreateChargeAsync(new StripeChargeInput
{
Amount = order.Total,
Currency = order.Currency,
IdempotencyKey = $"charge:{order.Id}",
}, ct);
await ctx.Entities.Order.UpdateAsync(order.Id, new OrderUpdate
{
Status = OrderStatus.Paid,
ChargeId = charge.Id,
}, ct);
await ctx.Events.EmitAsync("order.paid", new { OrderId = order.Id }, ct);
return new ChargeResult(true, charge.Id);
}
}What you get
Source-generator typed
Records and interfaces emitted at build-time from your project's contract manifest. Compile-time safety end-to-end.
Manifest verification
The SDK refuses to talk to a server whose generated-format version it does not support. Fail closed.
Realtime built-in
WebSocket and SSE subscriptions through ClientWebSocket. IAsyncEnumerable streams. Reconnect-safe.
DI-friendly
AddVadylClient extension on IServiceCollection. Plays naturally with ASP.NET Core, MAUI, Blazor.
Native AOT
Trimming-safe and AOT-compatible. Ships as a single binary.
Branch-aware
Configure branches per environment via VadylClientOptions.Branch. Sandbox testing without leaving prod.
OpenTelemetry
Built-in ActivitySource and Meter integration. Spans on every canonical operation.
Agent primitives
VadylClient.Agents exposes the Agent plane: definitions, runs, memory, MCP exposure.
Connections
Typed governed-connection clients per registered governed connection.
Deep-dive documentation
Build with the C# SDK in minutes.
Install the package and work with your product model through typed entities, workflows, agents, and events.