Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
159769 stories
·
33 followers

How to Find an Exact Gmail Thread with Codex or Claude

1 Share
Use Gmail’s Message-ID to point Codex or Claude at one exact email and retrieve the complete conversation rather than a plausible result.
Read the whole story
alvinashcraft
23 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

An Overview of Agent Memory for .NET

1 Share

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??

Overview of Agent Memory for .NET

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.

Key Features and Innovations

Types of Memory:

    • Short-term Memory: This component captures the immediate context of conversations, allowing agents to respond appropriately to ongoing dialogues.
    • Long-term Memory: This aspect stores a comprehensive knowledge graph that includes entities and relationships, enabling agents to recall past interactions and provide personalized responses.
    • Reasoning Memory: By recording the agent’s actions and decisions, this memory type enhances the agent’s ability to make informed decisions in future interactions.

    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.

    Implementation: Getting Started with Agent Memory for .NET

    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.

    Prerequisites

    Before you begin, ensure you have the following:

    • .NET SDK installed on your machine.
    • A running instance of Neo4j. You can download and install Neo4j from the official website.

    Code Example

    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
        }
    }

    Explanation of the Code

    1. Initialize Neo4j Driver: The first step is to create a connection to your Neo4j database using the GraphDatabase.Driver method. Replace the connection string and authentication details with your own.
    2. Create a Memory Store: An instance of MemoryStore is created, which will handle the storage and retrieval of memories.
    3. Store a Memory: The 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”.
    4. Retrieve a Memory: Finally, we retrieve the stored memory using the 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.

    Read the whole story
    alvinashcraft
    23 minutes ago
    reply
    Pennsylvania, USA
    Share this story
    Delete

    Google’s AI coding agent just escaped its own IDE

    1 Share
    A silhouette leans through an open doorway into a bright blue sky, casting a long beam of light across a dark blue floor; an artistic metaphor for solving the AI paradox.

    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.

    Agents inside every IDE

    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.

    Enterprise budgets and guardrails

    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.

    Token spending spirals quickly

    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%.

    Security policies follow authentication

    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.

    Read the whole story
    alvinashcraft
    1 hour ago
    reply
    Pennsylvania, USA
    Share this story
    Delete

    Flutter Performance Optimization: Fix Jank and Dropped Frames

    1 Share

    Flutter Performance Optimization: Fix Jank and Dropped Frames

    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.

    What Is Jank?

    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:

    • Expensive widget builds
    • Large synchronous computations
    • Excessive widget rebuilds
    • Poorly configured lists
    • Large images
    • Expensive layout or painting
    • Heavy work performed on the UI isolate
    • Excessive logging during animations

    The first rule of optimization is simple:

    Measure before changing code.

    Use Flutter's Performance Tools

    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.

    Look for Expensive Work in the UI Isolate

    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.

    Use Isolates for CPU-Heavy Work

    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:

    • Image processing
    • Large JSON transformations
    • Encryption
    • Parsing large datasets
    • Complex calculations

    The goal is to prevent CPU-heavy work from blocking UI responsiveness.

    Reduce Widget Rebuilds

    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}');
      },
    )
    

    Use const Widgets

    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.

    Optimize Long Lists

    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:

    • Stable item keys where necessary
    • Avoiding unnecessary nested scrolling
    • Efficient item layouts
    • Proper image caching
    • Pagination for large datasets

    Avoid Expensive Work in build()

    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.

    Optimize Images

    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.

    Be Careful with Opacity and Clipping

    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.

    Optimize Animations

    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.

    Watch for Excessive Logging

    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.

    Measure Again After Optimization

    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.

    A Practical Performance Checklist

    Before releasing a Flutter application, check:

    • Profile performance on physical devices
    • Inspect frame rendering in DevTools
    • Avoid heavy work in build()
    • Use isolates for CPU-heavy tasks
    • Reduce unnecessary rebuilds
    • Use lazy list builders
    • Optimize image dimensions
    • Avoid excessive compositing and clipping
    • Keep animations lightweight
    • Avoid excessive logging
    • Test on lower-end devices

    Conclusion

    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.

    Useful Links

    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

    Read the whole story
    alvinashcraft
    1 hour ago
    reply
    Pennsylvania, USA
    Share this story
    Delete

    PayPal Android SDK with Flutter: Integrate PayPal Checkout Using Platform Channels

    1 Share

    PayPal Android SDK with Flutter: Integrate PayPal Checkout Using Platform Channels

    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 PayPal module for checkout. The older PayPalNativeCheckout module was deprecated. Braintree also documents certificate-related requirements for older mobile SDKs, so verify the current SDK and migration guidance before production release.

    Step 1: Create the Flutter Project

    flutter create paypal_flutter_demo
    cd paypal_flutter_demo
    

    This tutorial focuses on Android.

    Step 2: Add the Android PayPal Dependency

    In the Android application's Gradle dependencies:

    dependencies {
        implementation("com.braintreepayments.api:paypal:5.8.0")
    }
    

    Verify the current Braintree version before production use.

    Step 3: Understand Credentials

    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.

    Step 4: Create the Flutter MethodChannel

    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.

    Step 5: Implement the Android Channel

    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()
                }
            }
        }
    }
    

    Step 6: Initialize the Native SDK

    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.

    Step 7: Start Checkout

    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.

    Step 8: Return the Result to Flutter

    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}');
    }
    

    Step 9: Verify Payments on Your Backend

    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.

    Step 10: Separate Flutter and Native Code

    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.

    Security Best Practices

    Never:

    • Hard-code private credentials.
    • Trust only a client-side success callback.
    • Log payment tokens.
    • Store sensitive credentials in ordinary preferences.
    • Fulfill orders without server-side verification.

    Use:

    • Backend-generated client authorization.
    • HTTPS.
    • Server-side transaction verification.
    • Current supported SDK versions.
    • Minimal logging of payment information.

    Why Platform Channels Matter

    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.

    Common Problems

    Dependency Resolution Failure

    Check the Android repository and dependency version required by the current Braintree documentation.

    Checkout Does Not Return to the App

    Check your App Link / return URL configuration.

    Payment Appears Successful but Order Is Not Updated

    Do not rely exclusively on the mobile callback. Verify the transaction on your backend.

    SDK Version Problems

    Payment SDKs change over time. Check the current Braintree migration and certificate guidance before releasing.

    Conclusion

    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!

    SEO Keywords

    Flutter SDK tutorial, Flutter integration, Flutter mobile development, Dart SDK integration, Flutter Android, Flutter iOS, SDK integration

    Tags

    flutter dart mobiledevelopment sdk android

    Useful Links

    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

    Read the whole story
    alvinashcraft
    1 hour ago
    reply
    Pennsylvania, USA
    Share this story
    Delete

    AI Won't Replace Project Managers, But It is Reshaping How Work Gets Done

    1 Share
    Read the whole story
    alvinashcraft
    2 hours ago
    reply
    Pennsylvania, USA
    Share this story
    Delete
    Next Page of Stories