Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
61 posts found
Designing Tools for Agents: Names, Descriptions, Schemas, Error Messages and Tool Count
Artificial Intelligence PART 03

Designing Tools for Agents: Names, Descriptions, Schemas, Error Messages and Tool Count

We compare twelve CRUD tools that mirror the API with two task-focused tools on the same requests with qwen3:4b: thirteen times the tokens, a book that can't be found and an agent that adds the wrong book and says "added". Why a schema isn't validation, human-readable output, messages that explain empty results, name collisions and side-effecting tools.

8 Nov 2026 13 min 5
Writing an Agent Loop from Scratch: Plan, Tool Call, Observation and Stop Condition
Artificial Intelligence PART 02

Writing an Agent Loop from Scratch: Plan, Tool Call, Observation and Stop Condition

We write an agent loop in C# without a framework: returning tool results and errors to the model, step/token/time budgets, blocking repeated calls and tracing every step. A real run shows tokens piling up turn by turn; then we do the same job with FunctionInvokingChatClient and MAF's ChatClientAgent and compare what each layer abstracts away.

8 Nov 2026 12 min 5
What Is an AI Agent? Workflows, Agents and Deciding You Don't Need One
Artificial Intelligence PART 01

What Is an AI Agent? Workflows, Agents and Deciding You Don't Need One

An agent is a system where the model directs the control flow; in a workflow, code draws the path. We run three Bookstore scenarios (order status, a return, find a book and add it to the cart) on the same code with qwen3:4b, measure model calls, tokens and time, and derive the price of an agent and the criteria for deciding you don't need one.

8 Nov 2026 11 min 5
From Semantic Kernel to Microsoft Agent Framework: History, Support Status and Migrating Old Code
Artificial Intelligence PART 14

From Semantic Kernel to Microsoft Agent Framework: History, Support Status and Migrating Old Code

Semantic Kernel still gets critical bug and security fixes, but new features go to Microsoft Agent Framework; the official commitment is at least one year after MAF GA (April 3, 2026). We build the history from NuGet and GitHub dates, run an old SK agent against a local model, migrate it to MAF and derive the mapping table.

8 Nov 2026 12 min 7
Hosting Agents in ASP.NET Core: AddAIAgent, OpenAI-Compatible Endpoints, AG-UI and A2A
Artificial Intelligence PART 13

Hosting Agents in ASP.NET Core: AddAIAgent, OpenAI-Compatible Endpoints, AG-UI and A2A

You register an agent in DI with AddAIAgent and expose it over three protocols with MapOpenAIChatCompletions, MapAGUIServer and MapA2AJsonRpc; the agent is written once and the adapters only translate the format. With real calls we look at an OpenAI response with multiple choices, an AG-UI stream that carries reasoning to the browser, the A2A agent card, and claims-based session isolation with rate limiting.

8 Nov 2026 11 min 5
Middleware, Context Providers and Session Persistence in Agent Framework
Artificial Intelligence PART 12

Middleware, Context Providers and Session Persistence in Agent Framework

In Agent Framework, agent run middleware handles inputs like card numbers, function invocation middleware blocks access to other customers' orders, and a context provider writes the user's preference into the session, which is saved and restored as JSON. In a real run we see the memory work, the model still invent an author, and reasoning bloat the session.

8 Nov 2026 11 min 5
Getting Started with Microsoft Agent Framework: From IChatClient to AIAgent
Artificial Intelligence PART 11

Getting Started with Microsoft Agent Framework: From IChatClient to AIAgent

AsAIAgent turns an IChatClient into a ChatClientAgent; the agent takes over instructions, function invocation and chat history through AgentSession, but it doesn't make the model smarter. We write the same Bookstore assistant first with a plain IChatClient and then as an agent, and compare RunAsync, RunStreamingAsync and AgentResponse with real outputs.

8 Nov 2026 9 min 7
Testing Code That Uses IChatClient: Fake Clients, Deterministic Tests and Microsoft.Extensions.AI.Evaluation
Artificial Intelligence PART 10

Testing Code That Uses IChatClient: Fake Clients, Deterministic Tests and Microsoft.Extensions.AI.Evaluation

You test the correctness of code that uses IChatClient with a fake client, without a model and in milliseconds; you measure the model's answer quality with Microsoft.Extensions.AI.Evaluation, in separate, cached evaluation runs. In real runs we see judge timeouts, reasoning hitting an 800-token cap, a cache returning stale answers, and a Relevance score that catches a prompt bug.

8 Nov 2026 15 min 7
Microsoft.Extensions.VectorData: Your First Collection with the Vector Store Abstraction
Artificial Intelligence PART 09

Microsoft.Extensions.VectorData: Your First Collection with the Vector Store Abstraction

Microsoft.Extensions.VectorData lets you define a record with attributes and move from an in-memory store to PostgreSQL + pgvector with the same code; the generator you give the store produces the embeddings. With real outputs we look at filtered search, ScoreThreshold, how the distance function flips the meaning of the score, and a dimension bug the InMemory provider never catches.

8 Nov 2026 11 min 4
Observing LLM Calls: UseOpenTelemetry, GenAI Semantic Conventions and the Aspire Dashboard
Artificial Intelligence PART 08

Observing LLM Calls: UseOpenTelemetry, GenAI Semantic Conventions and the Aspire Dashboard

To observe LLM calls, put UseOpenTelemetry inside UseFunctionInvocation, listen to the same source name with AddSource and read the trace in the Aspire Dashboard. In a real trace we find that a two-minute delay came from the Ollama queue rather than the model, and see how EnableSensitiveData carries an email address into telemetry.

8 Nov 2026 11 min 4
Controlling LLM Cost: DistributedCachingChatClient, Rate Limiting and Token Usage
Artificial Intelligence PART 07

Controlling LLM Cost: DistributedCachingChatClient, Rate Limiting and Token Usage

We control LLM cost in three layers: DistributedCachingChatClient with Redis answers repeated questions with zero tokens, per-user rate limiting limits abuse, and a daily token budget kept with UsageDetails limits real spending. With real output we show what goes into the cache key, that entries are written without expiry by default, and why token accounting must sit inside the cache.

8 Nov 2026 12 min 4
Taking Tool Calling to Production: FunctionInvokingChatClient Settings, DI Services and Approvals
Artificial Intelligence PART 06

Taking Tool Calling to Production: FunctionInvokingChatClient Settings, DI Services and Approvals

In production, on whose behalf a tool runs comes from the session, not from the model's arguments, and irreversible actions wait for user approval through ApprovalRequiredAIFunction. With real runs we show an OrderTools class using scoped services, FunctionInvokingChatClient settings, separating tool errors from user errors, and an approval flow over two HTTP requests.

8 Nov 2026 12 min 7
Blog Map