The ability for Microsoft Agent Framework agents to retain and utilize knowledge across interactions is critical. One solution for this is Agent Memory for .NET, a cutting-edge, mind-blowing, graph-native memory engine that leverages the robust capabilities of Neo4j as its backend. This framework is designed to empower AI agents with persistent memory, enabling them to provide contextually relevant responses and maintain continuity.
In this post, we will explore the key features, real-world applications, and implementation details of Agent Memory for .NET, along with a practical code example to get you started.

Get it? An elephant never forgets. Get it? Get it??
Agent Memory for .NET is a sophisticated solution that allows AI agents to store and recall information across sessions. By utilizing a graph database structure, that is, one that organizes data as nodes, edges and properties, it enables agents to create a rich knowledge graph that captures entities, relationships, and interactions over time.
Types of Memory:
Time-aware Memory: One of the standout features of Agent Memory for .NET is its support for bitemporal recall. Bitemporal recall is the ability of a data system to track and query information across two distinct timelines — in this case valid time (when the fact was true in the real world) and transaction time (when the fact was recorded in the Database). This allows agents to answer questions based on both past beliefs and current knowledge, providing a more nuanced understanding of user queries.
Integration: The framework is designed to be compatible with the Microsoft Agent Framework and other .NET applications. This seamless integration makes it easy for developers to incorporate Agent Memory into existing systems without significant overhead.
Graph-Native Structure: By leveraging Neo4j’s graph database capabilities, Agent Memory for .NET can store and query memory efficiently. This structure allows for complex relationships and interactions to be represented in a way that is both intuitive and powerful.
To illustrate how to set up Agent Memory for .NET, let’s walk through a simple code example. This demonstrates how to initialize the memory store, store a memory, and retrieve it.
Before you begin, ensure you have the following:
Here’s a straightforward example of how to set up Agent Memory for .NET using Neo4j:
using Neo4j.Driver;
using AgentMemory;
class Program
{
static async Task Main(string[] args)
{
// Initialize Neo4j Driver
var driver = GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "password"));
// Create a new memory store
var memoryStore = new MemoryStore(driver);
// Store a memory
await memoryStore.StoreMemory("user123", "What is the capital of France?", "Paris");
// Retrieve a memory
var response = await memoryStore.RetrieveMemory("user123", "What is the capital of France?");
Console.WriteLine(response); // Outputs: Paris
}
}
GraphDatabase.Driver method. Replace the connection string and authentication details with your own.MemoryStore is created, which will handle the storage and retrieval of memories.StoreMemory method is called to save a memory associated with a specific user. In this case, we store the question “What is the capital of France?” along with the answer “Paris”.RetrieveMemory method and print the response to the console.By leveraging the power of Neo4j, Agent Memory for .NET provides a solution for enhancing applications with persistent memory.
For more information and resources, see the Agent Memory for .NET GitHub Repository and the Neo4j Blog on Agent Memory.
When Google launched Antigravity in November 2025, it was on the premise that developers could hand an entire coding task to an AI agent and let it run. But developers still need to work directly in their code editor.
Google announced Thursday that it is expanding Antigravity into developers’ existing workflows through new extensions for Visual Studio Code, Visual Studio, JetBrains IDEs and Zed. The company is also making Antigravity available through eligible Gemini Enterprise subscriptions.
The extensions let developers open agent conversations in a side panel, review inline diffs, inspect plans and delegate multi-step engineering tasks without moving a project into the Antigravity 2.0 desktop application. The same Antigravity account works across each environment, so users don’t have to sign in or manage licenses separately.
The VS Code extension is available now via Microsoft’s extension marketplace on macOS, Linux, and Windows, while the extension for Visual Studio 2026 and .NET solutions is currently in preview. Google is also supporting the JetBrains suite (including IntelliJ IDEA, PyCharm, WebStorm, GoLand, CLion, and Rider) starting with version 2026.2.1, alongside Zed.
Meeting developers in their editor of choice makes it far easier for Google to land inside enterprise engineering teams, where people rarely use the exact same setup.
Admins can turn on Google’s developer tools for employees on Gemini Enterprise Standard, Plus or Standard Emerging Market plans. They can also cap monthly spending for each Google Cloud project. When the included quota runs out, Antigravity either shuts off or switches to pay-as-you-go pricing. Google says controls for individual users and teams are coming later this year.
Until then, everyone in the same edition, project, and region draws from a single pool of credits. Google explains the allowance as monthly but meters it using a rolling seven-day pool. Anything left disappears when the pool resets.
A nontrivial engineering task can consume 150,000 to 200,000 tokens, while multi-agent handoffs add more input tokens each time work passes between agents.
That quota can go quickly. A nontrivial engineering task can consume 150,000 to 200,000 tokens, while multi-agent handoffs add more input tokens each time work passes between agents. One built-in Claude Code skill was recently found to be loading more than 200,000 tokens before answering a question. Without a default allocation for each developer, an agent-heavy workflow could burn through the team’s entire pool within hours.
Google is not the first vendor to confront this problem. Microsoft recently introduced AI token budgets for its engineering divisions after discovering that many of its engineers were spending hundreds to thousands of dollars per month on tokens. Uber reportedly exhausted its entire 2026 AI coding budget in the first four months of the year. An internal Amazon project meant to match author records with product listings exceeded its planned budget by 860%.
Enterprise developers sign in with their company credentials, then choose the Google Cloud project and region Antigravity should use. Organizations can connect to their existing identity provider via Workforce Identity Federation, while developers can also authenticate using Application Default Credentials.
Once authenticated, agent sessions inherit the organization’s IAM policies, VPC Service Controls and regional data boundaries. Google says data from enterprise Antigravity sessions is not used to train its foundation models.
Once one of those connections reaches a production system, a bad setting can have serious consequences.
Admins can limit an agent’s workspace, block browser access, and decide which MCP servers it can use. Once one of those connections reaches a production system, a bad setting can have serious consequences. ElevenLabs’ MCP server, for example, let Claude delete production voice agents from a chat window. A connection with that kind of power needs to be treated like any other privileged access.
Putting Antigravity inside existing editors lets Google get its agents onto developers’ machines without requiring a company-wide tooling change, while Gemini Enterprise keeps every session tied to the same policies and project budget regardless of whether it starts in VS Code or JetBrains. Developers can switch editors without changing what the agent can reach or how its usage is billed.
The extension gets Antigravity through the door; the control plane determines what it can do once it is inside.
The post Google’s AI coding agent just escaped its own IDE appeared first on The New Stack.
Flutter can render extremely smooth interfaces, but poorly optimized widgets, expensive synchronous work, excessive rebuilds, and inefficient lists can cause jank and dropped frames.
In this tutorial, we will look at a systematic approach to finding and fixing Flutter performance problems.
A smooth UI needs to produce frames quickly enough to keep animations responsive. When a frame takes too long to render, the user notices stuttering or delayed interaction.
Common causes include:
The first rule of optimization is simple:
Measure before changing code.
Flutter DevTools provides tools for understanding CPU usage, memory, frame rendering, widget rebuilds, and network activity.
Run your application in profile mode when evaluating real performance.
flutter run --profile
Debug mode is useful for development but should not be used as the final benchmark.
Dart code executed on the main isolate can compete with UI work.
Avoid doing large computations directly inside a build method.
Bad example:
@override
Widget build(BuildContext context) {
final processed = expensiveCalculation(items);
return ListView(
children: processed.map(buildItem).toList(),
);
}
The calculation can execute whenever the widget rebuilds.
Move expensive work outside the build path.
final processed = calculateItems(items);
return ListView(
children: processed.map(buildItem).toList(),
);
For genuinely CPU-heavy operations, consider moving the computation to another isolate.
For expensive CPU-bound tasks, Dart provides isolate APIs.
final result = await Isolate.run(() {
return expensiveCalculation(input);
});
This can be useful for tasks such as:
The goal is to prevent CPU-heavy work from blocking UI responsiveness.
One common performance problem is rebuilding a large widget tree when only a small part changed.
Instead of rebuilding everything:
setState(() {
counter++;
});
structure the widget tree so that only the necessary section depends on the changing state.
State management libraries such as BLoC can also help by allowing targeted rebuilds.
BlocBuilder<CartBloc, CartState>(
buildWhen: (previous, current) {
return previous.total != current.total;
},
builder: (context, state) {
return Text('\$${state.total}');
},
)
Flutter can optimize constant widget instances.
const Text('Hello Flutter');
Prefer const constructors when the widget and its parameters are compile-time constants.
For example:
class EmptyState extends StatelessWidget {
const EmptyState({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text('No items found'),
);
}
}
Using const everywhere is not a magic performance solution, but it is a useful part of a clean widget tree.
For large collections, prefer lazy builders.
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ProductTile(item: items[index]);
},
)
Avoid constructing thousands of widgets at once with a large children list when the content can be built lazily.
For complex lists, also consider:
The build() method should primarily describe the UI.
Avoid:
Widget build(BuildContext context) {
final json = jsonDecode(largeJsonString);
final sorted = sortLargeCollection(data);
return MyWidget(data: sorted);
}
Instead, perform those operations when the data changes and pass the prepared result to the UI.
Large images can consume substantial memory and increase decoding work.
If a thumbnail is displayed at a small size, downloading a massive source image is inefficient.
Use appropriately sized assets or request resized images from your backend.
For local images, consider:
Image.asset(
'assets/images/product.png',
cacheWidth: 400,
)
The appropriate size depends on the target device and display density.
Some visual effects can be more expensive than simple painting, especially when combined with complex widget trees.
Instead of repeatedly wrapping large subtrees in expensive effects, consider whether the effect can be applied to a smaller widget.
Also avoid unnecessary clipping, shadows, and compositing layers in frequently animated areas.
Animations should avoid unnecessary work on every frame.
Keep animated regions small when possible.
Use Flutter's animation APIs rather than manually triggering frequent state updates.
AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: expanded ? 300 : 100,
child: const Placeholder(),
)
Implicit animations can be a clean solution for straightforward transitions.
Logging large objects repeatedly during an animation or scrolling operation can affect performance.
Avoid code such as:
print(largeResponseObject);
inside frequently executed callbacks.
Use structured logging and reduce verbose logging in release builds.
Performance optimization should be iterative:
Measure
↓
Identify bottleneck
↓
Change one thing
↓
Measure again
↓
Compare results
Without measurement, it is easy to optimize code that was never a real bottleneck.
Before releasing a Flutter application, check:
build()
Flutter performance problems are usually easier to solve when you treat them as measurement problems rather than guessing games.
Start with profiling, identify the slow operation, make a focused change, and measure again. With efficient widget trees, lazy lists, optimized images, targeted rebuilds, and isolates for expensive CPU work, you can eliminate many common sources of jank and deliver a much smoother Flutter experience.
Website: www.v-modal.com
SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter
SDK Android: https://github.com/v-modal/vmodal_sdk_android
Discord: https://discord.gg/K72z28KUx
Flutter does not need a Dart package for every native Android SDK. When an application depends on an Android-only SDK, Flutter can communicate with Kotlin through platform channels.
This is especially useful for payment SDKs.
In this tutorial, we'll demonstrate the architecture for integrating the PayPal Android SDK through Braintree's PayPal module into a Flutter Android application.
Important: Braintree's current Android documentation recommends the
PayPalmodule for checkout. The olderPayPalNativeCheckoutmodule was deprecated. Braintree also documents certificate-related requirements for older mobile SDKs, so verify the current SDK and migration guidance before production release.
flutter create paypal_flutter_demo
cd paypal_flutter_demo
This tutorial focuses on Android.
In the Android application's Gradle dependencies:
dependencies {
implementation("com.braintreepayments.api:paypal:5.8.0")
}
Verify the current Braintree version before production use.
Do not put private credentials in Flutter.
The mobile client can use an appropriate client authorization value such as a client token or tokenization key, depending on the integration.
For production, obtain client authorization from your backend.
import 'package:flutter/services.dart';
class PayPalBridge {
static const _channel = MethodChannel(
'com.example.paypal/checkout',
);
static Future<String?> startCheckout() {
return _channel.invokeMethod<String>(
'startCheckout',
);
}
}
Flutter platform channels allow Dart to call Android Kotlin code.
In MainActivity.kt:
class MainActivity : FlutterActivity() {
private val channelName = "com.example.paypal/checkout"
override fun configureFlutterEngine(
flutterEngine: FlutterEngine
) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
channelName
).setMethodCallHandler { call, result ->
when (call.method) {
"startCheckout" -> {
startPayPalCheckout(result)
}
else -> result.notImplemented()
}
}
}
}
Braintree's Android documentation shows creating a PayPalLauncher in Activity.onCreate() and creating a PayPalClient with an authorization value and app-link return URL.
Conceptually:
private lateinit var payPalLauncher: PayPalLauncher
private lateinit var payPalClient: PayPalClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
payPalLauncher = PayPalLauncher()
payPalClient = PayPalClient(
context = this,
authorization = clientAuthorization,
appLinkReturnUrl = Uri.parse(
"https://merchant-app.example"
)
)
}
Use the exact current API from the SDK version you install.
Keep the payment implementation in a dedicated class:
private fun startPayPalCheckout(
result: MethodChannel.Result
) {
// Start the current PayPal checkout flow.
// Return success or error through `result`.
}
Avoid putting the entire payment implementation into MainActivity.
Success:
result.success("completed")
Failure:
result.error(
"PAYPAL_ERROR",
"Payment could not be completed",
null
)
Flutter:
try {
final status = await PayPalBridge.startCheckout();
if (status == 'completed') {
debugPrint('Checkout completed');
}
} on PlatformException catch (e) {
debugPrint('PayPal error: ${e.message}');
}
Never treat a mobile callback as the only source of truth for fulfilling an order.
Use:
Flutter
↓
Native PayPal SDK
↓
PayPal / Braintree
↓
Backend
↓
Verify transaction
↓
Fulfill order
Your backend should verify payment state before marking an order as paid.
A clean structure:
lib/
payments/
paypal_bridge.dart
android/
app/
src/main/kotlin/
PayPalManager.kt
MainActivity.kt
PayPalBridge should expose a small Dart API.
PayPalManager should own Android-specific payment logic.
Never:
Use:
Flutter's platform-channel architecture allows Dart to communicate with Android Kotlin/Java APIs. This makes it possible to use native SDKs when a suitable Flutter plugin is unavailable.
Check the Android repository and dependency version required by the current Braintree documentation.
Check your App Link / return URL configuration.
Do not rely exclusively on the mobile callback. Verify the transaction on your backend.
Payment SDKs change over time. Check the current Braintree migration and certificate guidance before releasing.
SDK integrations are easiest to maintain when credentials, platform-specific configuration, networking, and UI responsibilities are separated. Start with the smallest working flow, verify it on a physical device, and then add production concerns such as authentication, error handling, lifecycle management, and secure credential handling.
Stay tuned for more advanced Flutter SDK integration tutorials!
Flutter SDK tutorial, Flutter integration, Flutter mobile development, Dart SDK integration, Flutter Android, Flutter iOS, SDK integration
flutter dart mobiledevelopment sdk android
Website: www.v-modal.com
SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter
SDK Android: https://github.com/v-modal/vmodal_sdk_android
Discord: https://discord.gg/K72z28KUx