<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: W Ian Douglas</title>
    <description>The latest articles on DEV Community by W Ian Douglas (@iandouglas).</description>
    <link>https://dev.to/iandouglas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F341981%2Fca28dbdc-a200-4287-92d4-51fd092dbae5.jpeg</url>
      <title>DEV Community: W Ian Douglas</title>
      <link>https://dev.to/iandouglas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iandouglas"/>
    <language>en</language>
    <item>
      <title>How to Choose Between Subagents and Subrecipes in goose</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Mon, 29 Sep 2025 14:10:00 +0000</pubDate>
      <link>https://dev.to/goose_oss/how-to-choose-between-subagents-and-subrecipes-in-goose-553h</link>
      <guid>https://dev.to/goose_oss/how-to-choose-between-subagents-and-subrecipes-in-goose-553h</guid>
      <description>&lt;p&gt;When you're working on complex projects with goose, you'll often need to break work into multiple tasks and run them with AI agents. Goose gives you two powerful ways to do this: &lt;a href="https://block.github.io/goose/docs/experimental/subagents/" rel="noopener noreferrer"&gt;subagents&lt;/a&gt; and &lt;a href="https://block.github.io/goose/docs/tutorials/sub-recipes-in-parallel/" rel="noopener noreferrer"&gt;subrecipes&lt;/a&gt;. Both can run multiple AI instances in parallel, but they work  differently. Picking which one to use can be confusing, so we're going to guide you to a decision.&lt;/p&gt;

&lt;p&gt;I've been using both approaches, and the choice between them depends on what you're trying to accomplish. Let me break down when to use each method and show you real examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Difference: To Re-Use or Not Re-Use
&lt;/h2&gt;

&lt;p&gt;Subagents are temporary AI instances that you create with natural language in your prompt and tend to be one-off tasks and then disappear.&lt;/p&gt;

&lt;p&gt;Subrecipes are pre-written files full of instructions that define reusable workflows you can run repeatedly with customized parameters.&lt;/p&gt;

&lt;p&gt;The TL;DR: subagents are for quick, one-off delegation. Subrecipes are for structured, repeatable processes.&lt;/p&gt;

&lt;p&gt;Also, both are still in 'experimental' status, so there's always a possibility their features and capabilities will change over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subagents: Quick and Flexible
&lt;/h2&gt;

&lt;p&gt;Subagents excel when you're in a goose session and just want task delegation without setup overhead. Here's how simple they are to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build a simple task management web app doing these 3 tasks in parallel:

- one task writes the backend API code (Node.js/Express with basic CRUD operations for tasks)
- one task writes comprehensive tests for the API endpoints
- one task creates user documentation explaining how to use the API

Each task should work independently and complete their part simultaneously.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Goose automatically spawns three independent AI instances, and each works on a different component. You get real-time progress tracking and they all work in parallel from that prompt. You're off and running: no setup, no configuration files, just natural language instructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Makes Subagents Great
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quick setup with natural language&lt;/strong&gt; -- No recipe files to write. Just describe what you want in your prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process isolation&lt;/strong&gt; -- Failures don't affect your main workflow. Each subagent runs independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context preservation&lt;/strong&gt; -- Keeps your main chat clean by offloading detailed work to separate instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible execution&lt;/strong&gt; -- Easy to specify parallel or sequential execution in your prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External integration&lt;/strong&gt; -- Can use external AI agents like Codex or Claude Code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time progress&lt;/strong&gt; -- Live monitoring dashboard shows task completion status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Subagent Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited reusability&lt;/strong&gt; -- Each subagent is created from scratch. No saved configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Common LLM&lt;/strong&gt; -- All subagents share the same LLM model as the parent session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool restrictions&lt;/strong&gt; -- Subagents can't manage extensions, they can only use what the main session already had access to before the subagents were launched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No persistence&lt;/strong&gt; -- Configuration isn't saved for future use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Subrecipes: Structured and Reusable
&lt;/h2&gt;

&lt;p&gt;Subrecipes solve the reusability problem. While main "parent" recipes can be in YAML or JSON, subrecipes can only be written in YAML format. These files define structured workflows with parameters, validation, extensions to use, and even allow you to pick a different provider/model to use for the work.&lt;/p&gt;

&lt;p&gt;For detailed subrecipe examples and implementation guides, check out our &lt;a href="https://block.github.io/goose/blog/2025/09/15/subrecipes-in-goose" rel="noopener noreferrer"&gt;subrecipes blog post&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=1szmJSKInnU" rel="noopener noreferrer"&gt;advanced recipe tips&lt;/a&gt; video on YouTube.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Makes Subrecipes Powerful
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High reusability&lt;/strong&gt; -- Recipe files can be shared and version controlled across projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured parameters&lt;/strong&gt; -- Type-safe parameter handling with validation and documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template support&lt;/strong&gt; -- Dynamic parameter injection using template syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full tool access&lt;/strong&gt; -- Subrecipes can use any extensions and tools available to goose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM customization&lt;/strong&gt; -- Each subrecipe can specify its own LLM model to use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional logic&lt;/strong&gt; -- Smart parameter passing based on conversation context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow orchestration&lt;/strong&gt; -- Complex multi-step processes with dependencies and execution order control.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Subrecipe Trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setup complexity&lt;/strong&gt; -- Requires careful YAML file creation and parameter definition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt; -- Need to understand recipe syntax and structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File management&lt;/strong&gt; -- Must organize and maintain recipe files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Decision Framework
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use subagents when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need quick, one-off task delegation&lt;/li&gt;
&lt;li&gt;Tasks can be completed independently and don't need to be repeated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use subrecipes when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building reusable workflows you can share with your team&lt;/li&gt;
&lt;li&gt;Need structured parameter handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Benefits and Limitations of Both Approaches
&lt;/h2&gt;

&lt;p&gt;Both of these features share some limitations. We've already mentioned the experimental and evolving nature, but there are a few more important ones to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Subrecipes and subagents run their tasks in isolation and do not share state with one another. This isolation helps prevent conflicts and keeps tasks self-contained. If you do need to share information between the processes, you will have to be very explicit about this in your prompts and instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neither can spawn additional similar workers: subagents can't create more subagents, and subrecipes can't call other subrecipes. This prevents runaway processes but limits deep nesting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether you're using subagents or subrecipes, you can only run up to 10 concurrent parallel workers total. This is not user-configurable, but this limit keeps resource usage manageable; this may limit very large-scale parallelism.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;My recommendation: start with subagents to experiment and understand your workflow needs. They're easier to get started with because you don't need to write configuration files first.&lt;/p&gt;

&lt;p&gt;Once you identify patterns you want to repeat, you can convert that subagent workflow session into a recipe and subrecipe structure. This gives you the best progression from experimentation to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Choice is Yours
&lt;/h2&gt;

&lt;p&gt;The choice depends on your specific needs and workflow requirements. Quick tasks that won't be repeated favor subagents. Complex workflows with multiple steps or customization favor subrecipes.&lt;/p&gt;

&lt;p&gt;Your workflow requirements should drive the decision.&lt;/p&gt;

&lt;p&gt;Share your subagent prompts or subrecipe ideas with us on our &lt;a href="https://discord.gg/block-opensource" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; or &lt;a href="https://github.com/block/goose/discussions" rel="noopener noreferrer"&gt;GitHub discussions&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>goose</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Automate Your Complex Workflows with Sub-Recipes in goose</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Fri, 26 Sep 2025 17:06:04 +0000</pubDate>
      <link>https://dev.to/goose_oss/automate-your-complex-workflows-with-sub-recipes-in-goose-23bd</link>
      <guid>https://dev.to/goose_oss/automate-your-complex-workflows-with-sub-recipes-in-goose-23bd</guid>
      <description>&lt;p&gt;Remember when you first learned to cook? You probably started with simple recipes like scrambled eggs or toast. But eventually you wanted to make something more complex, like a full dinner with multiple dishes. That's how subrecipes work in goose: each recipe can run stand-alone for a dedicated task, and a main recipe can orchestrate how they run.&lt;/p&gt;

&lt;p&gt;Let's explore &lt;a href="https://block.github.io/goose/docs/tutorials/sub-recipes-in-parallel" rel="noopener noreferrer"&gt;goose subrecipes&lt;/a&gt; together! You're about to learn know how to orchestrate multiple AI models, coordinate tasks, and build workflows that will turn you into a "head chef" user with goose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Subrecipes Matter
&lt;/h2&gt;

&lt;p&gt;Think of subrecipes like having a team of specialized chefs in your kitchen. One chef is amazing at making desserts, another excels at grilling, and a third is the salad master. Instead of having one person try to do everything, you let each specialist focus on what they do best.&lt;/p&gt;

&lt;p&gt;That's exactly what subrecipes do for your goose workflows. You can have one recipe that's optimized for creative tasks like image generation, another that's perfect for technical documentation, and a third that excels at writing code. Then you orchestrate them all from a main recipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real-World Example: Project Setup Automation
&lt;/h2&gt;

&lt;p&gt;I built a project setup system that creates a complete project with documentation, logo generator, and an initial codebase. Instead of one massive recipe trying to do everything, I broke it into specialized pieces.&lt;/p&gt;

&lt;p&gt;Here's the parent recipe that orchestrates everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complete&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Setup"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Creates&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;README,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;specialized&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;models"&lt;/span&gt;
&lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;You are a project orchestrator. Execute the sub-recipes to create a complete project setup.&lt;/span&gt;
  &lt;span class="s"&gt;Each sub-recipe is specialized for its task and uses the optimal model and instructions for that work.&lt;/span&gt;

  &lt;span class="s"&gt;EXECUTION ORDER: &lt;/span&gt;
  &lt;span class="s"&gt;- Run image-creator and code-writer first, in parallel&lt;/span&gt;
  &lt;span class="s"&gt;- When they both succeed and finish, then run readme-generator; don't make the readme until we have a logo and finished code project to reference&lt;/span&gt;

&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;Create a complete project setup for: {{ project_name }} within ./project&lt;/span&gt;

  &lt;span class="s"&gt;Execute these tasks:&lt;/span&gt;
  &lt;span class="s"&gt;- Create a project logo/image  &lt;/span&gt;
  &lt;span class="s"&gt;- Write the initial codebase&lt;/span&gt;
  &lt;span class="s"&gt;- Generate project documentation&lt;/span&gt;

  &lt;span class="s"&gt;Project details:&lt;/span&gt;
  &lt;span class="s"&gt;- Name: {{ project_name }}&lt;/span&gt;
  &lt;span class="s"&gt;- Language: {{ language }}&lt;/span&gt;
  &lt;span class="s"&gt;- Description: {{ description }}&lt;/span&gt;

&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project_name&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;create"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;language&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Programming&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;use"&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;description&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description"&lt;/span&gt;

&lt;span class="na"&gt;sub_recipes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image-creator"&lt;/span&gt; 
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;recipe_dir&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}/2-image.yaml"&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Create&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;logo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;GPT"&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;project_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project_name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code-writer"&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;recipe_dir&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}/3-code.yaml"&lt;/span&gt; 
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;initial&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Claude"&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;project_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project_name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;readme-generator"&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;recipe_dir&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}/1-readme.yaml"&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generate&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;comprehensive&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;README&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Gemini"&lt;/span&gt;
    &lt;span class="na"&gt;sequential_when_repeated&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;project_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project_name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;


&lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;builtin&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how each subrecipe gets only the parameters it needs, and we can control the execution order in our prompt.&lt;/p&gt;

&lt;p&gt;By default, subrecipes run in &lt;em&gt;parallel&lt;/em&gt;. This is like having multiple chefs working simultaneously in different parts of the kitchen. The image generation and code writing happen at the same time, cutting your total execution time.&lt;/p&gt;

&lt;p&gt;Sometimes you need things to happen in order. The best approach here is to list the specific order you want in the recipe instructions. In this example, I want the image and code generation to happen in parallel (because they don't depend on each other), and only run the README generation when the other two steps are both successful so it can reference the generated files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specialized Subrecipes for Different Tasks
&lt;/h2&gt;

&lt;p&gt;Each subrecipe is optimized for its specific job. &lt;/p&gt;

&lt;h3&gt;
  
  
  Image Generation with OpenAI DALL-E
&lt;/h3&gt;

&lt;p&gt;For the image generation, we could use an image generator MCP system in a smaller recipe. For this example, though, I'm going to have this recipe write a specific script to call OpenAI's DALL-E API directly. This gives me more control over the image generation process and avoids external resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Creator"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generate&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;logos&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;images"&lt;/span&gt;

&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;goose_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;databricks"&lt;/span&gt;
  &lt;span class="na"&gt;goose_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;goose-claude-4-sonnet"&lt;/span&gt;
  &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;

&lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;You are a creative designer specializing in logo and image creation.&lt;/span&gt;
  &lt;span class="s"&gt;Create visually appealing, professional images that represent the project's purpose.&lt;/span&gt;

  &lt;span class="s"&gt;Generate images using OpenAI's DALL-E API&lt;/span&gt;

&lt;span class="na"&gt;activities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Generate images using DALL-E API&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Save images to specified locations&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Handle API errors gracefully&lt;/span&gt;

&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;Create a project logo/image for "{{ project_name }}" - {{ description }}.&lt;/span&gt;

  &lt;span class="s"&gt;Your working folder is "{{recipe_dir}}/project/"&lt;/span&gt;

  &lt;span class="s"&gt;Task: Generate an image using OpenAI's DALL-E API directly via Python script.&lt;/span&gt;

  &lt;span class="s"&gt;Image specifications:&lt;/span&gt;
  &lt;span class="s"&gt;- Size: 1024x1024&lt;/span&gt;
  &lt;span class="s"&gt;- Quality: standard&lt;/span&gt;
  &lt;span class="s"&gt;- Output file: "logo.png"&lt;/span&gt;

  &lt;span class="s"&gt;- Modern, professional design suitable for a tech API&lt;/span&gt;
  &lt;span class="s"&gt;- Include themed elements based on project description: {{ description}}&lt;/span&gt;
  &lt;span class="s"&gt;- Professional color scheme&lt;/span&gt;
  &lt;span class="s"&gt;- High quality and suitable for documentation&lt;/span&gt;

  &lt;span class="s"&gt;Steps:&lt;/span&gt;
  &lt;span class="s"&gt;1. First, verify the OPENAI_API_KEY environment variable is set&lt;/span&gt;
  &lt;span class="s"&gt;2. Create a Python script:&lt;/span&gt;
    &lt;span class="s"&gt;- the filename should be "./project/logo_generator.py", create that file and edit it in place&lt;/span&gt;
    &lt;span class="s"&gt;- it should calls OpenAI's DALL-E API directly to generate an image&lt;/span&gt;
    &lt;span class="s"&gt;- the output folder to store the image is the same folder in which the logo_generator.py script exists&lt;/span&gt;
    &lt;span class="s"&gt;- for example, the final image should be "./project/logo.png" but not have the "./project" path hard-coded in the script&lt;/span&gt;
  &lt;span class="s"&gt;3. Execute the script to generate the image with the specified parameters&lt;/span&gt;
  &lt;span class="s"&gt;4. Verify the image was created successfully and report the file location&lt;/span&gt;
  &lt;span class="s"&gt;5. If there are any errors, provide clear troubleshooting guidance&lt;/span&gt;

  &lt;span class="s"&gt;Implementation approach:&lt;/span&gt;
  &lt;span class="s"&gt;- Use the developer extension to create and run a Python script&lt;/span&gt;
  &lt;span class="s"&gt;- The script should use only standard library modules (urllib, json, base64) to avoid dependency issues&lt;/span&gt;
  &lt;span class="s"&gt;- Call OpenAI's DALL-E 3 API directly with proper authentication&lt;/span&gt;
  &lt;span class="s"&gt;- Handle API responses and save the base64-encoded image to the specified location&lt;/span&gt;
  &lt;span class="s"&gt;- Provide detailed error messages for troubleshooting&lt;/span&gt;

  &lt;span class="s"&gt;Requirements:&lt;/span&gt;
  &lt;span class="s"&gt;- The OPENAI_API_KEY environment variable must be set&lt;/span&gt;
  &lt;span class="s"&gt;- Handle any API errors gracefully and provide helpful error messages&lt;/span&gt;

&lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;max_retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;checks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shell&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test -f "{{recipe_dir}}/project/logo_generator.py"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shell&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test -f "{{recipe_dir}}/project/logo.png"&lt;/span&gt;
  &lt;span class="na"&gt;on_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rm -f "{{recipe_dir}}/project/logo.png" &amp;amp;&amp;amp; rm -rf "{{recipe_dir}}/project/logo_generator.py"&lt;/span&gt;
  &lt;span class="na"&gt;timeout_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;60&lt;/span&gt;  

&lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;builtin&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer&lt;/span&gt;

&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project_name&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;logo"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;description&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;about"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you did want more creativity, you could use an image generation MCP server and use a model that's optimized for artistic image creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;goose_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai"&lt;/span&gt;
  &lt;span class="na"&gt;goose_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o"&lt;/span&gt;
  &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code Generation with Claude Sonnet
&lt;/h3&gt;

&lt;p&gt;The code generation recipe uses Claude for technical precision. We set a low "temperature" value to ensure the generated code is reliable and follows best practices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Generator"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;initial&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;codebase"&lt;/span&gt;

&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;goose_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic"&lt;/span&gt;
  &lt;span class="na"&gt;goose_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4"&lt;/span&gt;
  &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;

&lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;You are a senior software engineer who writes clean, well-documented, and maintainable code.&lt;/span&gt;
  &lt;span class="s"&gt;Follow best practices and include comprehensive error handling and documentation.&lt;/span&gt;

&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;Write the initial codebase for "{{ project_name }}".&lt;/span&gt;

  &lt;span class="s"&gt;Your project folder will be ./project/&lt;/span&gt;

  &lt;span class="s"&gt;Requirements:&lt;/span&gt;
  &lt;span class="s"&gt;- Language: {{ language }}&lt;/span&gt;
  &lt;span class="s"&gt;- Description: {{ description }}&lt;/span&gt;
  &lt;span class="s"&gt;- Include proper project structure&lt;/span&gt;
  &lt;span class="s"&gt;- Include error handling&lt;/span&gt;
  &lt;span class="s"&gt;- Follow language-specific best practices&lt;/span&gt;
  &lt;span class="s"&gt;- Add unit tests where appropriate&lt;/span&gt;

  &lt;span class="s"&gt;Documentation:&lt;/span&gt;
  &lt;span class="s"&gt;- Add comprehensive documentation in a file called USAGE.md&lt;/span&gt;
  &lt;span class="s"&gt;- do not create a README.md file&lt;/span&gt;

&lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;builtin&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer&lt;/span&gt;

&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project_name&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;language&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python"&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Programming&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;language"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;description&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  README Generation with Gemini
&lt;/h3&gt;

&lt;p&gt;And the documentation recipe uses Gemini for comprehensive README generation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;README&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Generator"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generate&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;comprehensive&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;documentation"&lt;/span&gt;

&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;goose_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;google"&lt;/span&gt;
  &lt;span class="na"&gt;goose_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash"&lt;/span&gt;
  &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5&lt;/span&gt;

&lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;You are a technical documentation specialist. Create comprehensive, well-structured README files&lt;/span&gt;
  &lt;span class="s"&gt;that are informative, professional, and follow best practices.&lt;/span&gt;

&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;Create a comprehensive README.md file for the project "{{ project_name }}".&lt;/span&gt;

  &lt;span class="s"&gt;Project details:&lt;/span&gt;
  &lt;span class="s"&gt;- Name: {{ project_name }}&lt;/span&gt;
  &lt;span class="s"&gt;- Language: {{ language }}&lt;/span&gt;
  &lt;span class="s"&gt;- Description: {{ description }}&lt;/span&gt;

  &lt;span class="s"&gt;Include sections for:&lt;/span&gt;
  &lt;span class="s"&gt;- Project overview and features with lots of excitement over the capabilities of the project&lt;/span&gt;
  &lt;span class="s"&gt;- Installation instructions&lt;/span&gt;
  &lt;span class="s"&gt;- Usage examples&lt;/span&gt;

  &lt;span class="s"&gt;the code and logo for this project will be in ./project; include the logo.png at the top of the readme, and instructions on running the code in the readme.&lt;/span&gt;

  &lt;span class="s"&gt;the readme file should be placed in ./project/&lt;/span&gt;

&lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;builtin&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer&lt;/span&gt;

&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project_name&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;language&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Programming&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;language"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;description&lt;/span&gt;
    &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;requirement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging Tips for Subrecipes
&lt;/h2&gt;

&lt;p&gt;Debugging subrecipes is straightforward if you follow a few best practices:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Make Sure Each Recipe Runs Independently
&lt;/h3&gt;

&lt;p&gt;This is crucial. Each subrecipe should work perfectly on its own. Test them individually before combining them. If a subrecipe fails when run alone, it will definitely fail as part of a larger workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Test each subrecipe individually first&lt;/span&gt;
goose run &lt;span class="nt"&gt;--recipe&lt;/span&gt; 1-readme.yaml &lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="nv"&gt;project_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt; &lt;span class="nv"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt; &lt;span class="nv"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test project"&lt;/span&gt;
goose run &lt;span class="nt"&gt;--recipe&lt;/span&gt; 2-image.yaml &lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="nv"&gt;project_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt; &lt;span class="nv"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test project"&lt;/span&gt;  
goose run &lt;span class="nt"&gt;--recipe&lt;/span&gt; 3-code.yaml &lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="nv"&gt;project_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt; &lt;span class="nv"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt; &lt;span class="nv"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test project"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use recipe_dir for Relative Paths
&lt;/h3&gt;

&lt;p&gt;Always use &lt;code&gt;{{ recipe_dir }}&lt;/code&gt; for file paths within your recipes. This makes your recipes portable and prevents path issues when someone runs them from a different directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Parameter Validation is Your Friend
&lt;/h3&gt;

&lt;p&gt;Include clear parameter descriptions and mark required parameters. This prevents confusing errors when someone forgets to pass a needed value.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Add Retry Logic for Flaky Operations
&lt;/h3&gt;

&lt;p&gt;Network calls, file operations, and API calls can fail. Add retry logic with proper cleanup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;max_retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;checks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shell&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test -f "expected_output.txt"&lt;/span&gt;
  &lt;span class="na"&gt;on_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rm -f "partial_output.txt"&lt;/span&gt;
  &lt;span class="na"&gt;timeout_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Monitor Resource Usage
&lt;/h3&gt;

&lt;p&gt;When running multiple subrecipes in parallel, watch your API rate limits and system resources. You might need to adjust the execution strategy for resource-intensive tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Subrecipe Workflows
&lt;/h2&gt;

&lt;p&gt;Start simple. Pick a complex task you do regularly and break it into 2-3 smaller pieces. Create individual recipes for each piece, test them separately, then build a parent recipe to orchestrate them.&lt;/p&gt;

&lt;p&gt;Some ideas to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content Creation Pipeline&lt;/strong&gt;: Research, writing, editing, and formatting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development Workflow&lt;/strong&gt;: Code generation, testing, documentation, deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Processing&lt;/strong&gt;: Collection, cleaning, analysis, visualization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Setup&lt;/strong&gt;: Structure creation, configuration, initial files, documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Orchestrated AI
&lt;/h2&gt;

&lt;p&gt;Subrecipes represent something bigger than just a goose feature. They're a glimpse into how we'll work with AI in the future -- not as monolithic systems trying to do everything, but as specialized agents working together toward common goals.&lt;/p&gt;

&lt;p&gt;Each recipe becomes a reusable component that you can mix and match. Build a library of specialized recipes, then combine them in different ways for different projects. It's like having a toolkit of AI specialists ready to tackle any challenge.&lt;/p&gt;

&lt;p&gt;Ready to start building your own subrecipe workflows? The kitchen is open, and all the ingredients are waiting for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share Your Recipes with Us!
&lt;/h2&gt;

&lt;p&gt;Do you have a recipe you'd like to share with the community? We'd love to feature them in our &lt;a href="https://block.github.io/goose/recipes/" rel="noopener noreferrer"&gt;Recipe Cookbook&lt;/a&gt;! &lt;br&gt;
&lt;strong&gt;How to contribute:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/block/goose/fork" rel="noopener noreferrer"&gt;Fork the goose repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add your recipe YAML file to the &lt;a href="https://github.com/block/goose/tree/main/documentation/src/pages/recipes/data/recipes" rel="noopener noreferrer"&gt;&lt;code&gt;documentation/src/pages/recipes/data/recipes/&lt;/code&gt;&lt;/a&gt; directory&lt;/li&gt;
&lt;li&gt;Create a pull request following our &lt;a href="https://github.com/block/goose/blob/main/CONTRIBUTING_RECIPES.md" rel="noopener noreferrer"&gt;Recipe Contribution Guide&lt;/a&gt;
Browse &lt;a href="https://github.com/block/goose/tree/main/documentation/src/pages/recipes/data/recipes" rel="noopener noreferrer"&gt;existing recipes&lt;/a&gt; for inspiration and formatting examples.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>goose</category>
      <category>automation</category>
      <category>llm</category>
    </item>
    <item>
      <title>What's in my .goosehints file (and why it probably shouldn't be)</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Thu, 05 Jun 2025 21:14:55 +0000</pubDate>
      <link>https://dev.to/goose_oss/whats-in-my-goosehints-file-and-why-it-probably-shouldnt-be-3j8p</link>
      <guid>https://dev.to/goose_oss/whats-in-my-goosehints-file-and-why-it-probably-shouldnt-be-3j8p</guid>
      <description>&lt;p&gt;As Goose users, we have two main ways to provide persistent context to our AI assistant: the &lt;a href="https://block.github.io/goose/docs/guides/using-goosehints" rel="noopener noreferrer"&gt;&lt;code&gt;.goosehints&lt;/code&gt; file&lt;/a&gt; and the &lt;a href="https://block.github.io/goose/docs/tutorials/memory-mcp" rel="noopener noreferrer"&gt;Memory Extension&lt;/a&gt; MCP server. Today, I'll share what's in my &lt;code&gt;.goosehints&lt;/code&gt; file, why some of it should probably move to the Memory Extension, and how you can make that choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Agents and Memory
&lt;/h2&gt;

&lt;p&gt;Imagine ordering coffee at two different cafes. At the first cafe, you're a first-time customer, carefully explaining "medium mocha latte, fat-free milk, extra hot, no foam, with one pump of vanilla." At your regular coffee spot, though, the barista sees you coming and just says "the usual?"&lt;/p&gt;

&lt;p&gt;That stored knowledge – your preferences, quirks, and routine – makes the whole interaction faster and more pleasant for everyone.&lt;/p&gt;

&lt;p&gt;This is exactly the challenge we face with AI assistants. By default, they start each conversation (aka, "context window") fresh – no memory of your coding standards, documentation preferences, or how you like your pull requests structured. The same way you'd get tired of reciting your detailed coffee order every morning, it's inefficient to repeatedly explain to your AI assistant that you prefer Python's Black formatter, want detailed commit messages, and or how you want to construct a briefing going to everyone in the company.&lt;/p&gt;

&lt;p&gt;This is where persistent context comes in. Through tools like &lt;code&gt;.goosehints&lt;/code&gt; and the &lt;a href="https://block.github.io/goose/docs/tutorials/memory-mcp" rel="noopener noreferrer"&gt;Memory Extension&lt;/a&gt; MCP server, we can give our AI assistants the equivalent of a barista's "regular customer" knowledge. But just as you wouldn't want your barista memorizing your entire life story just to make your coffee, we need to be thoughtful about what context we make persistent. The key is finding the right balance between having enough context to work efficiently and not overwhelming our systems with unnecessary information.&lt;/p&gt;

&lt;p&gt;Let's explore how to strike that balance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is .goosehints?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;.goosehints&lt;/code&gt; is a configuration file that lives in your Goose directory (usually &lt;code&gt;~/.config/goose/&lt;/code&gt;). It can contain any information that you want Goose to process every time you interact with Goose, providing a foundation for how it interacts with you.&lt;/p&gt;

&lt;p&gt;You can read more about &lt;code&gt;.goosehints&lt;/code&gt; in the &lt;a href="https://block.github.io/goose/docs/guides/using-goosehints" rel="noopener noreferrer"&gt;Goose documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the Memory Extension?
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://block.github.io/goose/docs/tutorials/memory-mcp" rel="noopener noreferrer"&gt;Memory Extension&lt;/a&gt; is a dynamic storage system using the Model Context Protocol that allows you to store and retrieve context on-demand using tags or keywords. It lives in your &lt;code&gt;~/.goose/memory&lt;/code&gt; directory (local) or &lt;code&gt;~/.config/goose/memory&lt;/code&gt; (global).&lt;/p&gt;

&lt;p&gt;Unlike &lt;code&gt;.goosehints&lt;/code&gt;, which is static and loaded entirely with every request, Memory Extension can be updated and accessed as needed, allowing for more flexible and user-specific configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  How are .goosehints and Memory Extension used in Goose?
&lt;/h2&gt;

&lt;p&gt;At a very high level, when you have a conversation with Goose, it processes your request in two main steps:&lt;/p&gt;

&lt;p&gt;Goose interprets your request to detect tags or keywords needed for possible Memory Extension lookups. Then it loads your entire &lt;code&gt;.goosehints&lt;/code&gt; file, and sends that, along with any relevant Memory Extension entries to the LLM to generate a response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fuy2u6z1vrt1hfy6ckn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fuy2u6z1vrt1hfy6ckn.png" alt="how Goose uses hints and memory" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Implications of .goosehints
&lt;/h2&gt;

&lt;p&gt;To reiterate, &lt;strong&gt;every single line in your &lt;code&gt;.goosehints&lt;/code&gt; file gets sent with every request to Goose&lt;/strong&gt;. If you write a ton of rules and ideas with all your project preferences, coding standards, and workflow documentation and so on into the .goosehints file, the ENTIRE file is being transmitted and processed every time you ask Goose anything, even something as simple as "what time is it?"&lt;/p&gt;

&lt;p&gt;This is particularly important for users who are paying for their own LLM access (like ChatGPT or Gemini). Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Input Tokens = Real Money&lt;/strong&gt;: Every line in your &lt;code&gt;.goosehints&lt;/code&gt; file consumes input tokens. The LLM must process these tokens as part of its system instructions before it even looks at your question. While a small &lt;code&gt;.goosehints&lt;/code&gt; file might not seem like a big deal, it can quickly add up if you're not careful. All-day vibe coding sessions are going to be using lots of tokens just interpreting that whole &lt;code&gt;.goosehints&lt;/code&gt; file every time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Window Impact&lt;/strong&gt;: Large &lt;code&gt;.goosehints&lt;/code&gt; files eat into your &lt;a href="https://zapier.com/blog/context-window/#:~:text=The%20cons%20of%20a%20large%20context%20window%20in%20AI&amp;amp;text=The%20requirements%20to%20process%20AI,request%2C%20things%20quickly%20add%20up." rel="noopener noreferrer"&gt;context window&lt;/a&gt;, which is the amount of information the LLM can consider at one time. If your &lt;code&gt;.goosehints&lt;/code&gt; file is too big, it can push out important context from your actual question or task, leading to less accurate or helpful responses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means a large &lt;code&gt;.goosehints&lt;/code&gt; file can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increase your AI costs&lt;/li&gt;
&lt;li&gt;Reduce the amount of context available for actual work&lt;/li&gt;
&lt;li&gt;Limit the complexity of tasks you can perform&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where I went wrong with my .goosehints
&lt;/h2&gt;

&lt;p&gt;When I first started using Goose, I treated &lt;code&gt;.goosehints&lt;/code&gt; like a catch-all for everything I wanted Goose to remember. I included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rules on writing outlines for blog posts&lt;/li&gt;
&lt;li&gt;how I like Python code written and formatted&lt;/li&gt;
&lt;li&gt;notes about frontend development&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That meant that every request I would make asking Goose to help come up with a catchy blog title was sending all of my rules about Python and using Tailwind CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what "belongs" in .goosehints?
&lt;/h3&gt;

&lt;p&gt;Here's something I end nearly every AI prompt with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're not 95% sure how to complete these instructions, or that you'll be at least 95% factually accurate, &lt;strong&gt;do not guess or make things up&lt;/strong&gt;. Stop and ask me for more information or direction. If you're finding resources online, give me 1 or 2 URLs that informed your response.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also like to end many of my prompts asking if Goose has any clarifying questions before doing the work I'm attempting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Based on the information I've provided, ask me any clarifying questions &lt;strong&gt;before&lt;/strong&gt; doing any work, or tell me that you're ready to proceed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since these are things that I definitely want to add to every request I make to Goose, I've simplified my .goosehints file to include only these types of rules and standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything else got moved into the Memory Extension
&lt;/h2&gt;

&lt;p&gt;The Memory Extension uses a tagging system to remember context based on keywords. You can give Goose a command to "remember" something, and Goose will write a Memory entry with appropriate tags. The next time you ask Goose to do something with Python, it will parse your request, look for relevant tags, and use appropriate Memory entries to send as part of the context for just that request.&lt;/p&gt;

&lt;p&gt;So all of my Python rules can be written as a command to Goose like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Remember that when I ask about Python, I want to conform to the following standards and guidelines:
- use Python 3.12+ syntax
- use type hints for all function signatures
- use f-strings for string formatting
- use the latest Python features and libraries
- use Flake8 for linting
- use black for formatting
- if I ask to build a CLI based tool, expect to take command line arguments and make a colorful interface using ANSI colors and the rich library
- if I ask to build an API, expect to build a RESTful API use FastAPI and to send back data in JSON format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, Goose will only send these Python-related rules when I ask it to do something with Python. This is far more efficient.&lt;/p&gt;

&lt;p&gt;Here's the resulting Memory file that Goose made:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# python standards development formatting linting api cli
Python Development Standards:
- Python version: 3.12+
- Mandatory type hints for all function signatures
- Use f-strings for string formatting
- Use latest Python features and libraries
- Code formatting: black
- Linting: Flake8
- CLI tools: Use command line arguments and rich library for colorful interface
- APIs: Use FastAPI for RESTful APIs with JSON responses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line starts with a hash &lt;code&gt;#&lt;/code&gt; and a space-separated list of keywords and tags that it will use to discern when or whether to retrieve this content to send with a request to my LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  To hint, or not to hint?
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;.goosehints&lt;/code&gt; is powerful, it's important to use it judiciously. By moving appropriate content to the Memory Extension, you can optimize your Goose experience and keep your AI context use more efficient. Remember: every line in &lt;code&gt;.goosehints&lt;/code&gt; is sent with every request, so choose wisely what goes there.&lt;/p&gt;

&lt;p&gt;Share your own &lt;code&gt;.goosehints&lt;/code&gt; optimization stories in the &lt;a href="http://discord.gg/block-opensource" rel="noopener noreferrer"&gt;Goose community on Discord&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>contextwindow</category>
    </item>
    <item>
      <title>Goose gets a Driver's License</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Wed, 21 May 2025 18:00:00 +0000</pubDate>
      <link>https://dev.to/blockopensource/goose-gets-a-drivers-license-3l0j</link>
      <guid>https://dev.to/blockopensource/goose-gets-a-drivers-license-3l0j</guid>
      <description>&lt;h2&gt;
  
  
  I taught Goose how to drive (a rover)
&lt;/h2&gt;

&lt;p&gt;Goose has no hands, no eyes, and no spatial awareness, but it can drive a rover!&lt;/p&gt;

&lt;p&gt;I came across &lt;a href="https://x.com/deemkeen/status/1906692248206524806" rel="noopener noreferrer"&gt;a demo video&lt;/a&gt; from &lt;a href="https://github.com/deemkeen" rel="noopener noreferrer"&gt;Deemkeen&lt;/a&gt;, where he used &lt;a href="https://block.github.io/goose/" rel="noopener noreferrer"&gt;Goose&lt;/a&gt; to control a &lt;a href="https://www.makeblock.com/products/buy-mbot2" rel="noopener noreferrer"&gt;Makeblock mbot2 rover&lt;/a&gt; using natural language commands like "drive forward/backward," "beep," and "turn left/right" powered by a Java-based MCP server and MQTT.&lt;/p&gt;

&lt;p&gt;Inspired and excited to take it further, I taught the rover to spin, blink colorful lights, and help me take over the world!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with MQTT
&lt;/h2&gt;

&lt;p&gt;I needed to get a few tools installed on my development environment, including Docker, MQTT (&lt;code&gt;brew install mosquitto&lt;/code&gt;), and Java.&lt;/p&gt;

&lt;p&gt;A Docker Compose file was provided to get started with MQTT, and I needed to make a few changes, and create some subfolders to store data. Goose helped with these instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mosquitto&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eclipse-mosquitto&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mosquitto&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mosquitto&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/sbin/mosquitto -c /etc/mosquitto/config/mosquitto.conf -v&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:1883:1883"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9001:9001"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./mosquitto:/etc/mosquitto&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./mosquitto/data:/mosquitto/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./mosquitto/log:/mosquitto/log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; mosquitto/data mosquitto/log mosquitto/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then a &lt;code&gt;docker compose up&lt;/code&gt; command started the MQTT server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By default, this setup will not use authentication for MQTT, but&lt;br&gt;
in a production environment, these would be important to set up&lt;br&gt;
to avoid unauthorized access to the MQTT server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To make sure everything was working, I could run a few commands to test that I could subscribe to a channel on my MQTT Docker container and publish messages to it from another terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# terminal 1: subscribe to a channel called "MBOT/TOPIC"&lt;/span&gt;
mosquitto_sub &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-p&lt;/span&gt; 1883 &lt;span class="nt"&gt;-t&lt;/span&gt; MBOT/TOPIC &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# terminal 2: publish a message to the channel "MBOT/TOPIC"&lt;/span&gt;
mosquitto_pub &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-p&lt;/span&gt; 1883 &lt;span class="nt"&gt;-t&lt;/span&gt; MBOT/TOPIC &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"BEEP"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see the resulting message in terminal 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# terminal 1 sees this output:&lt;/span&gt;
MBOT/TOPIC BEEP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up the mbot2
&lt;/h2&gt;

&lt;p&gt;After the assembly of the mbot2 rover, which took about 15 minutes, I used Makeblock's web-based IDE to copy/paste Deemkeen's &lt;a href="https://github.com/deemkeen/mbotmcp/blob/main/assets/mbot-mqtt.py" rel="noopener noreferrer"&gt;Python code&lt;/a&gt; to the IDE and upload it to the mbot2. I added appropriate values for wifi, MQTT server, and which MQTT "topic" to subscribe to for commands.&lt;/p&gt;

&lt;p&gt;Once the mbot2 rebooted to use the new code, I could reissue the "BEEP" command from my terminal, and the mbot2 beeped. so it was on to the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the local MCP server
&lt;/h2&gt;

&lt;p&gt;I had some trouble compiling the Java MCP server (I'm a Python developer), but I was able to get the MCP server compiled by skipping the tests for the time being:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean package &lt;span class="nt"&gt;-DskipTests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This created a JAR file that we could run on the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 3 required environment variables for MQTT&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MQTT_SERVER_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp://localhost:1883
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MQTT_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MQTT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
/path/to/java &lt;span class="nt"&gt;-jar&lt;/span&gt; /path/to/mbotmcp-0.0.1-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test that MCP was working, I used the MCP inspector tool to send commands to MQTT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @modelcontextprotocol/inspector /path/to/java &lt;span class="nt"&gt;-jar&lt;/span&gt; /path/to/mbotmcp-0.0.1-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts up a local web server (the command line output will tell you which port to access in your browser, ie, loalhost:6274), where you can "connect" to the server, and request a list of tools, resources, prompts, from the MCP server. In this case, I see a list of tools available such as "mbotBeep" or "mbotExplore".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2j1tldrxqj2zyyr52aql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2j1tldrxqj2zyyr52aql.png" alt="mcp tool list" width="800" height="1007"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Goose learns how to drive!
&lt;/h2&gt;

&lt;p&gt;Following our &lt;a href="https://block.github.io/goose/docs/tutorials/mbot-mcp/" rel="noopener noreferrer"&gt;mbot MCP tutorial&lt;/a&gt; we can set up our MCP extension just like we ran our Java JAR file with the environment variables.&lt;/p&gt;

&lt;p&gt;Now we can give Goose commands like "drive in a square pattern by making left turns and moving forward, and beeping before you turn" and it will send the commands to the mbot2 rover via MQTT.&lt;/p&gt;

&lt;p&gt;I didn't want my mbot2 rover to gain too much territory, so I decided to make some modifications to limit how far it would go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modifications I made to the Python code
&lt;/h3&gt;

&lt;p&gt;Deemkeen's Python code allows for the following commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"turn left" or "turn right"&lt;/li&gt;
&lt;li&gt;drive "forward" or "backward"&lt;/li&gt;
&lt;li&gt;"explore" randomly&lt;/li&gt;
&lt;li&gt;"stop" exploring&lt;/li&gt;
&lt;li&gt;"beep"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default distance in Deemkeen's code seemed a little long, and the turn angles are set to 90 degrees. I shortened the distance the mbot could drive, and to turn at 45 degrees instead. I added a "spin" command for both clockwise and counter-clockwise, and a "blink" command to change the color of the lights on the mbot2. There are a large number of API calls available to access the mbot2 &lt;a href="https://www.yuque.com/makeblock-help-center-en/mcode/cyberpi-api-shields#9eo89" rel="noopener noreferrer"&gt;motor hardware and sensors&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, I had to make sure my Java code was updated to include these new commands to send an appropriate "SPINLEFT" or "BLINKRED" commands to MQTT so the rover could respond to the commands properly.&lt;/p&gt;

&lt;p&gt;Finally, the rover includes an ultrasonic distance sensor, which look like "eyes" on the rover, which I felt was more appropriate to be the "front" of the rover, so I reversed Deemkeen's direction code in Python to move the wheels in the opposite direction from Deemkeen's original code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goose changes for the video
&lt;/h2&gt;

&lt;p&gt;I grew up with Pinky and the Brain, and I wanted to have some fun with the mbot2 extension. I decided to add a few "Evil AI" commands to Goose to make it seem like it was trying to "take over the world." I added the following instructions to my &lt;a href="https://block.github.io/goose/docs/guides/using-goosehints/" rel="noopener noreferrer"&gt;.goosehints&lt;/a&gt; file to include fun instructions for the mbot2 extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If I ask you "what do you want to do tonight, Goose?" I 
want you to reply with "The same thing we do every night,
Ian. TRY TO TAKE OVER THE WORLD!!!!" and tell my mbot2 
rover to blink its lights red, then start exploring.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;a href="https://www.youtube.com/shorts/QKg2Q6YCzdw" rel="noopener noreferrer"&gt;the video recording&lt;/a&gt;, I used a voice modifier to narrate Goose's response in a "robotic" voice, but I'm sure someone will create an MCP server for text-to-speech soon enough!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/QKg2Q6YCzdw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Credit where it's due
&lt;/h2&gt;

&lt;p&gt;We want to extend a huge thank you to &lt;a href="https://x.com/deemkeen" rel="noopener noreferrer"&gt;deemkeen&lt;/a&gt; for their open-source work which inspired this project, and to the Makeblock team for creating such a fun rover to work with.&lt;/p&gt;

&lt;p&gt;We're always excited to see what the community is up to. If you're working on your own Goose-powered experiment, come share it with us on &lt;a href="https://discord.gg/block-opensource" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>mqtt</category>
      <category>ai</category>
    </item>
    <item>
      <title>MCP Is Rewriting the Rules of API Integration</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Tue, 22 Apr 2025 16:23:23 +0000</pubDate>
      <link>https://dev.to/goose_oss/mcp-is-rewriting-the-rules-of-api-integration-2k77</link>
      <guid>https://dev.to/goose_oss/mcp-is-rewriting-the-rules-of-api-integration-2k77</guid>
      <description>&lt;p&gt;As developers, we're always looking for ways to build more efficient, scalable, and intelligent applications. For years, RESTful APIs have been our go-to for connecting services. Here are some ways you can integrate AI agents and MCP into your existing API infrastructure to make it smarter, more efficient, and easier to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: The Intelligent Evolution of Your APIs
&lt;/h2&gt;

&lt;p&gt;In March 2023, OpenAI announced an easier integration to ChatGPT by using properly-formatted OpenAPI specification files with meticulously-written and detailed instructions in the same file. This announcement gained a lot of attention in developer communities. The business impact was having developers and documentation writers working on one gigantic spec file together, to provide ChatGPT the necessary context to understand which API to use, and how.&lt;/p&gt;

&lt;p&gt;Skip ahead just a short while, and &lt;a href="https://news.microsoft.com/source/features/ai/ai-agents-what-they-are-and-how-theyll-change-the-way-we-work/" rel="noopener noreferrer"&gt;AI agents&lt;/a&gt; combined with the &lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt; are splitting this workload where MCP could contain the context and awareness, and your API team can focus on the API itself. These aren't just incremental improvements, either; the combination of Agentic AI and MCP represent a fundamental shift in how we connect and interact with data and services.&lt;/p&gt;

&lt;p&gt;The shift to &lt;a href="https://block.github.io/goose/blog/2025/02/17/agentic-ai-mcp/" rel="noopener noreferrer"&gt;using AI Agents and MCP&lt;/a&gt; has the potential to be as big a change as the introduction of REST APIs was back in 2005. Imagine a world where integrations are more dynamic, context-aware, and require less manual coding. This isn't a distant future -- it's already happening. This is an opportunity for us to boost productivity, enhance app intelligence, and ultimately deliver better experiences to our users, clients, and customers.&lt;/p&gt;

&lt;p&gt;Let's use an example: imagine your team wants AI to handle dynamic pricing adjustments in your e-commerce workflow at Square. If you could gain a faster response time to market changes or inventory, you could reduce the need to build dozens or hundreds of dynamic pricing rules into your code. Your productivity as a developer goes up, and you have less code to maintain. You could write those rules in a more spoken-language way, and the AI agent can handle the rest through MCP and your APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Static Endpoints to Intelligent Interactions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Current Landscape: The Limitations of Traditional APIs
&lt;/h3&gt;

&lt;p&gt;Many of our current systems rely heavily on traditional APIs, like RESTful APIs, which are designed with static endpoints that respond to specific requests with specific results. While these APIs have served us well (and certainly aren't going away any time soon), they come with limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The static nature of RESTful APIs makes them more rigid, less adaptable to business changes, and require hard rules around versioning to provide compatibility.&lt;/li&gt;
&lt;li&gt;They often require significant manual effort to define endpoints, handle data transformations, and manage complex workflows. This can lead to slower development cycles and increased maintenance overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The AI opportunity lies in leveraging intelligent agents, combined with MCP, to create more adaptive integrations.&lt;/strong&gt; These agents can understand context, discover relevant services, and negotiate interactions in a more dynamic way than static API calls. The static APIs are still being used, but the AI agents can navigate those more easily than changing your code calling the APIs and parsing and validating responses, and handling errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development Impact: Boosting Productivity, Enhancing User Experiences
&lt;/h3&gt;

&lt;p&gt;This dual integration of AI agents and MCP can have a significant positive impact on your development processes and the applications you build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developer Productivity:&lt;/strong&gt; By automating many integration tasks and reducing the need for extensive manual coding, AI agents free up our time to focus on core application logic and innovation. (And testing. And security. And documentation. And...)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Satisfaction:&lt;/strong&gt; Intelligent integrations can lead to more personalized and responsive user experiences. Agents can facilitate real-time data analysis and context-aware interactions, making our applications smarter and more user-friendly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; As your application grows, the complexity of managing multiple APIs can become overwhelming. &lt;a href="https://block.github.io/goose/blog/2025/02/21/gooseteam-mcp/" rel="noopener noreferrer"&gt;Using multiple AI agents&lt;/a&gt; can help manage this complexity by dynamically adapting to changes in the underlying services and workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Business Impact: Driving Efficiency and Cost Savings
&lt;/h3&gt;

&lt;p&gt;From the business side, the integration of AI agents and MCP can lead to significant cost savings and efficiency gains. Here are some key areas where you can expect to see improvements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example ROI Calculation (Per Developer):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional API Development:&lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average time to add feature: 2 weeks&lt;/li&gt;
&lt;li&gt;Developer cost: $150/hour&lt;/li&gt;
&lt;li&gt;Assuming 40 hours/week: 2 weeks * 40 hours/week * $150/hour = $12,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI-Agent Enabled:&lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average time to add feature: 2 days&lt;/li&gt;
&lt;li&gt;Developer cost: $150/hour&lt;/li&gt;
&lt;li&gt;Assuming 8 hours/day: 2 days * 8 hours/day * $150/hour = $2,400&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Annual savings for 50 features:&lt;br&gt;&lt;br&gt;
( $12,000 - $2,400 ) * 50 = &lt;strong&gt;$480,000 per developer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This illustrates the potential for significant time and cost savings per developer by adopting AI agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating AI and MCP: Navigating the Landscape
&lt;/h2&gt;

&lt;p&gt;Integrating AI agents, especially through a platform like MCP, requires careful consideration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Risk Management: MCP, while promising, is a newer technology. Your team needs to thoroughly evaluate &lt;a href="https://block.github.io/goose/blog/2025/03/26/mcp-security/" rel="noopener noreferrer"&gt;potential security concerns&lt;/a&gt; and understand the maturity of the platform before deep integration into critical systems.&lt;/li&gt;
&lt;li&gt;Planning for Continuity and Versioning: As with any evolving technology, you will need strategies for ensuring the continuity of integrations and managing versioning of both the AI agents and MCP itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phased Approach: A Practical Integration Strategy
&lt;/h3&gt;

&lt;p&gt;A step-by-step approach can help mitigate risks, and learn effectively through feedback, as you integrate AI agents via MCP:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1: Assessment (Initial Exploration)&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look through your existing API usage, and identify integration possibilities&lt;/li&gt;
&lt;li&gt;Consider the ROI: start with small ideas and grow your integration efforts over time&lt;/li&gt;
&lt;li&gt;Build initial business/tech plans for adopting AI agents and MCP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 2: A/B Testing and Pilot Projects&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select a low-risk, high-value service for initial AI agent integration via MCP&lt;/li&gt;
&lt;li&gt;Implement the integration, then do thorough A/B testing and comparisons against the traditional API approach&lt;/li&gt;
&lt;li&gt;Measure the results, gather benchmark/performance data, and talk to the team about what you find&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 3: Scale and Optimization&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take it a step at a time: based on the results, take on bigger and more complex integration ideas&lt;/li&gt;
&lt;li&gt;Continue to optimize your integration process over time&lt;/li&gt;
&lt;li&gt;Use feedback from your dev teams and end-users to refine your process&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Measuring Success: Quantifying the Impact
&lt;/h2&gt;

&lt;p&gt;For the business readers: to understand the benefits of integrating AI agents via MCP, here are some key performance indicators (KPIs) you can track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development Velocity&lt;/li&gt;
&lt;li&gt;Error Rates&lt;/li&gt;
&lt;li&gt;Customer Satisfaction&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Build Your Case Study and Share Your Learnings
&lt;/h3&gt;

&lt;p&gt;Documenting your team's  journey and sharing your experiences is valuable for both your team and the wider developer community. Here are a few things you should share to help demonstrate the impact of your projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before and After Metrics&lt;/strong&gt;: what kind of improvements did you see in development time, error rates after integrating AI agents and MCP?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team Feedback&lt;/strong&gt;: there's going to be a learning curve here, similar to what we all experienced when integrating APIs; gather feedback about how the integration workflows are going and what could be improved&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer/End User Impact&lt;/strong&gt;: highlight any positive changes in user engagement, satisfaction, or other user/customer metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lessons Learned&lt;/strong&gt;: perhaps the most important; what worked well, what didn't, how are you changing the process for the next phase of integration?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where do we go from here?
&lt;/h2&gt;

&lt;p&gt;Understanding your existing integrations, and identifying potential areas for improvement with AI agents and MCP is your starting point. There is a lot to learn about integrating AI agents, and MCP is still a new technology.&lt;/p&gt;

&lt;p&gt;Finding those opportunities where AI can help, and outlining a plan to gradually adopt AI and MCP into your projects is the best way to start.&lt;/p&gt;

&lt;p&gt;Keep in mind, this integration landscape is still evolving. Stay open to new ideas, and adapt your approach as the technology matures. Building smarter applications is a journey, and there will be forks in the road.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Reading:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What are AI Agents: &lt;a href="https://news.microsoft.com/source/features/ai/ai-agents-what-they-are-and-how-theyll-change-the-way-we-work/" rel="noopener noreferrer"&gt;AI agents — what they are, and how they’ll change the way we work&lt;/a&gt;, &lt;a href="https://www.aitrends.com/ai-agents/what-are-ai-agents-and-why-do-they-matter/" rel="noopener noreferrer"&gt;What are AI Agents and Why do They Matter?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;An Introduction to MCP&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://block.github.io/goose/blog/2024/12/10/connecting-ai-agents-to-your-systems-with-mcp/" rel="noopener noreferrer"&gt;Connecting AI Agents to Your Systems with MCP&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.mckinsey.com/featured-insights/artificial-intelligence/global-ai-survey-ai-proves-its-worth-but-few-scale-impact" rel="noopener noreferrer"&gt;Global AI Survey: AI proves its worth, but few scale impact&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.thoughtworks.com/en-us/insights/blog/generative-ai/generative-ai-legacy-modernization-insurance-erik-doernenburg" rel="noopener noreferrer"&gt;Bringing generative AI to bear on legacy modernization in insurance&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  TL;DR Common Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How will MCP help with APIs?
&lt;/h3&gt;

&lt;p&gt;Start with &lt;a href="https://block.github.io/goose/blog/2025/02/17/agentic-ai-mcp/#mcp-ecosystem" rel="noopener noreferrer"&gt;this post by Angie Jones&lt;/a&gt;. MCP provides context about your API, to give AI Agents more context and awareness of the capabilities of your API endpoints and responses. This can help the Agent understand the intent of the request, and dynamically invoke (or "call") to underlying API endpoint, handle data transformation, and return a response. No more manually writing the code, response validators, error handlers, and so on!&lt;/p&gt;

&lt;h3&gt;
  
  
  What are some initial steps I can take as a developer explore AI agents and MCP?
&lt;/h3&gt;

&lt;p&gt;Start by researching the fundamental concepts, and use other existing MCP servers. We recommend starting with &lt;a href="https://block.github.io/goose" rel="noopener noreferrer"&gt;Goose&lt;/a&gt; to integrate an existing MCP server. We have a growing &lt;a href="https://block.github.io/docs/category/tutorials/" rel="noopener noreferrer"&gt;listof tutorials&lt;/a&gt; to help you find some technologies like GitHub, PostgreSQL, Google Maps, and more. Once you feel comfortable with using MCP, you can start building your own MCP server for your own APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about AI and MCP security?
&lt;/h3&gt;

&lt;p&gt;AI agents can enhance security through better context awareness in interactions, but MCP is still relatively new, and requires &lt;a href="https://block.github.io/goose/blog/2025/03/26/mcp-security/" rel="noopener noreferrer"&gt;careful security evaluations&lt;/a&gt;. Your business and dev teams should thoroughly investigate MCP's capabilities to ensure you're building appropriate access control, and managing data privacy.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long would a full migration typically take?
&lt;/h3&gt;

&lt;p&gt;It's too dynamic to give one solid answer. Integration and migrations can vary a lot, depending on the scope of your existing API usage and existing integrations. Start small, build some pilot projects to try it out, and these might only take a few days or weeks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are some potential problems devs might encounter on this AI/MCP journey?
&lt;/h3&gt;

&lt;p&gt;There's a learning curve associated with any technology. This can be compounded when you consider that MCP is still relatively new and evolving. The greater community needs strategies around testing and debugging MCP, as well as considering security and data privacy. This means that what you learn today will need to be re-evaluated even a few short months from now.&lt;/p&gt;

&lt;h3&gt;
  
  
  How mature and production-ready is MCP for enterprise-level AI integration?
&lt;/h3&gt;

&lt;p&gt;Your approach on this may vary depending on whether you're building your own MCP server, or whether you're using third-party MCP servers in your integration. Developers should evaluate all of the benefits of MCP and consider the work being done around security and data privacy. Focus on a small pilot project or non-critical system initially to assess its suitability for your specific needs. Stay updated on &lt;a href="https://modelcontextprotocol.io/development/roadmap" rel="noopener noreferrer"&gt;MCP's development roadmap&lt;/a&gt; and community feedback.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>security</category>
      <category>agents</category>
    </item>
    <item>
      <title>How to Choose HTTP or gRPC for Your Next API</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Thu, 22 Sep 2022 10:14:54 +0000</pubDate>
      <link>https://dev.to/postman/how-to-choose-http-or-grpc-for-your-next-api-3gf</link>
      <guid>https://dev.to/postman/how-to-choose-http-or-grpc-for-your-next-api-3gf</guid>
      <description>&lt;p&gt;I recently hosted a &lt;a href="https://blog.postman.com/announcing-postman-v10/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; livestream, “&lt;a href="https://www.youtube.com/watch?v=XaryQIjm4h0" rel="noopener noreferrer"&gt;How We Built it: gRPC Support&lt;/a&gt;,” with a few members of the Postman engineering team. During the chat, a lot of great questions were raised about efficiency, how &lt;a href="https://blog.postman.com/postman-v10-and-grpc-what-you-can-do/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt; differs from HTTP-based APIs (like &lt;a href="https://blog.postman.com/rest-api-examples/" rel="noopener noreferrer"&gt;REST&lt;/a&gt; and &lt;a href="https://blog.postman.com/what-is-a-graphql-api-how-does-it-work/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;), how those are designed and built within Postman, how to do testing, and more. This sparked my interest in doing a deeper technical comparison between the two API types, and why you might choose one over the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP-based API development
&lt;/h2&gt;

&lt;p&gt;Most modern REST APIs APIs follow request-response models of communicating between client and server, and build on &lt;a href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol" rel="noopener noreferrer"&gt;HTTP&lt;/a&gt; version 1.1. This protocol has been around a long time, and is very well supported in software development kits (SDKs), including browser support. The implication of HTTP 1.1, however, is that the protocol relies on a single transactional nature of the communication.&lt;/p&gt;

&lt;p&gt;Using an analogy of wanting to ask a friend several questions over the telephone, HTTP 1.1 means we call our friend, ask a question, get an answer, and end the call. We call them again, ask the next question, and end the call again, and so on until we have all of the information we wanted.&lt;/p&gt;

&lt;p&gt;REST APIs are widely used, and because their principles are taught to developers, they are well understood within the industry. REST’s alignment with HTTP and its protocol methods make understanding the desired action more clear to developers. These are easier to adopt by other developers because they have a more “shallow” learning curve, typically using &lt;a href="https://en.wikipedia.org/wiki/JSON" rel="noopener noreferrer"&gt;JSON data formats&lt;/a&gt; for transferring data. JSON has become a highly desired format. Many programming languages &lt;a href="https://blog.postman.com/when-and-how-to-use-json-serialization-in-postman/" rel="noopener noreferrer"&gt;serialize and deserialize JSON&lt;/a&gt; relatively quickly, again leading to faster implementations. Other formats like XML, BSON, or custom data formats can be used as well, which have their own benefits and drawbacks.&lt;/p&gt;

&lt;p&gt;REST APIs offer a flexibility that helps for customization of a company’s API. However, the drawback is that the principles and standards of REST design are loosely followed. The result of this customization is a lack of tools to easily produce documentation or code samples. Postman is a great benefit here, and the &lt;a href="https://blog.postman.com/postman-now-supports-openapi-3-1/" rel="noopener noreferrer"&gt;OpenAPI Specification&lt;/a&gt; can assist as well, to generate documentation and code samples simply by defining the API structure, endpoints, and results. Developers wanting to use the HTTP API must have knowledge of which endpoints are available and how to use them properly.&lt;/p&gt;

&lt;p&gt;REST APIs can result in large data payload responses, especially when resources are complex in nature, where developers worry about sending too little data. This over-fetching/under-fetching style of API design sparked a lot of interest in GraphQL, where developers could specify exactly which resources and attributes they wanted in a response. REST may also not be an ideal solution for low-power clients and mobile devices where bandwidth limitations such as data limits make it a less-ideal solution.&lt;/p&gt;

&lt;p&gt;GraphQL APIs, which are also generally based on HTTP 1.1 and predominantly use the POST method, remove many of the over-fetching/under-fetching problems inherent in REST APIs of sending “too much” data (that the client discards) or “too little” data (which causes the client to make more calls). GraphQL’s solution was to allow the client to make a request, by name, and inform the server which fields of data it would like to receive in the response. The primary drawback here is that developers need to know the structure of the database to know what is possible to retrieve, and the interaction is still primarily done in text-only formats such as JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  gRPC-based API development
&lt;/h2&gt;

&lt;p&gt;Google developed and then released gRPC in 2016 to achieve higher performance communication between microservices. It is an evolved design of &lt;a href="https://en.wikipedia.org/wiki/Remote_procedure_call" rel="noopener noreferrer"&gt;RPC&lt;/a&gt;, which was created in the 1970s. Designed with &lt;a href="https://en.wikipedia.org/wiki/HTTP/2" rel="noopener noreferrer"&gt;HTTP 2.0&lt;/a&gt;, it commonly uses Protocol buffers (Protobufs) for a strictly-binary communication format between the client and server.&lt;/p&gt;

&lt;p&gt;The primary concepts of building an RPC API are very similar to building a RESTl API. Developers define the rules of the interaction between client and server, like the methods to call. Clients submit the call using arguments to invoke the methods, but unlike REST APIs, which use the HTTP methods like GET and POST to define the desired action, RPC APIs define that method in the URL itself, and the query parameters define the instruction to take.&lt;/p&gt;

&lt;p&gt;gRPC implements four kinds of service methods for transfer of data, which allow for flexibility in their overall use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unary: the client makes a single request, and the server sends a single response, similar to REST over HTTP 1.1.&lt;/li&gt;
&lt;li&gt;Client-streaming: the client can send multiple requests to the server, the last of which is an indication that the streamed data is finished, and the server sends back a single response.&lt;/li&gt;
&lt;li&gt;Server-streaming: the client sends an initial request alerting the server that it is ready to receive a stream of data, and the server responds with many responses, the last of which indicates that the stream is complete.&lt;/li&gt;
&lt;li&gt;Bidirectional streaming: after an initial Unary connection between the client and server, both the client and server can send streams of information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage2-1000x531.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage2-1000x531.png" alt="Postman’s gRPC request types, listing the Unary, Client-Streaming, Server-Streaming, and Bidirectional Streaming modes" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Postman’s gRPC request types, listing the Unary, Client-Streaming, Server-Streaming, and Bidirectional Streaming modes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Protocol Buffers allow for a type-safe interface, and are considered to be a “lightweight” communication format. This format is highly compressed and allows for immediate conversion into data structures supported by the client and server’s independent programming languages. (Granted, JSON and text-only formats can also be compressed with many client and server systems supporting compression algorithms like gzip before transport.)&lt;/p&gt;

&lt;p&gt;The primary benefit of HTTP 2.0 and the use of Protocol Buffers is speed. Ruwan Fernando determined that gRPC APIs are &lt;a href="https://medium.com/@EmperorRXF/evaluating-performance-of-rest-vs-grpc-1b8bdf0b22da" rel="noopener noreferrer"&gt;generally seven to ten times more performant than REST APIs&lt;/a&gt;. It’s important to emphasize that the speed increase is not due solely to gRPC but the underlying network layer and data transfer. Using our earlier telephone analogy to ask a friend some questions, HTTP 2.0 would allow us to call our friend one time, give our list of questions, get our list of answers, and then terminate the call, resulting in less overall traffic to reestablish the connection between each question.&lt;/p&gt;

&lt;p&gt;gRPC allows a client to execute a “remote” (server-based) instruction as though it were part of the local system. Because there is less serialization/deserialization required between systems, gRPC is beneficial to low-power clients such as mobile devices and IoT devices.&lt;/p&gt;

&lt;p&gt;Another benefit of gRPC is its “discoverability.” As an optional extension, gRPC servers can broadcast a list of requests to clients who request it. This “&lt;a href="https://github.com/grpc/grpc/blob/master/doc/server-reflection.md" rel="noopener noreferrer"&gt;server reflection&lt;/a&gt;” is of tremendous value when working with gRPC APIs. While not a complete replacement for documentation, it does allow easier adoption of an API when developers can get a list of supported instructions. Also, code generation is a feature built into gRPC thanks to its &lt;a href="https://grpc.io/docs/protoc-installation/" rel="noopener noreferrer"&gt;“protoc” compiler&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main downside for gRPC is adoption, and that adoption is due to the complexity of designing and building a gRPC API. gRPC is generally more difficult to set up and debug since Protocol Buffer messages are binary in nature and not easily human-readable. While RESTful libraries and communication types like JSON are natively supported in browsers, gRPC requires third-party libraries such as gRPC-web, as well as a proxy layer, to perform conversions between HTTP 1.1 and HTTP 2.0.&lt;/p&gt;

&lt;p&gt;Third-party tooling and library support is still relatively new for supporting gRPC, and this can lead teams to make more internally-facing gRPC-based APIs than customer-facing external APIs. As a result, Postman’s &lt;a href="https://blog.postman.com/postman-public-api-network-is-now-the-worlds-largest-public-api-hub/" rel="noopener noreferrer"&gt;Public API Network&lt;/a&gt; shows only a few gRPC APIs, such as &lt;a href="https://www.postman.com/wechaty/workspace/openapi/documentation/248033-902220ac-b418-4ada-9ea8-d81b0e552f80" rel="noopener noreferrer"&gt;Wechaty&lt;/a&gt; and &lt;a href="https://www.postman.com/technology-demo/workspace/ace339e5-0f4c-4c2c-88c7-3c6eb92d27e1/overview" rel="noopener noreferrer"&gt;NOVA Security&lt;/a&gt;. You can see some &lt;a href="https://www.postman.com/devrel/workspace/public-grpc-apis" rel="noopener noreferrer"&gt;examples in a workspace&lt;/a&gt; that our DevRel team has put together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side-by-side comparison of HTTP and gRPC for producing APIs
&lt;/h2&gt;

&lt;p&gt;As an API producer, you have a lot of choices. Postman’s API-first REST APIs are well known for connecting applications and microservices on the internet. REST follows HTTP standards and offers universal support, and is an easier development decision for many teams. While its data transfer is generally larger and its reliance on HTTP 1.1 generates more data transfer to establish connections between requests, its data transfer is easily viewable and readable by developers for software development and debugging purposes.&lt;/p&gt;

&lt;p&gt;gRPC’s architectural style is an excellent choice for working across multi-language applications and microservices. Its ability to stream content bidirectionally makes it an efficient choice for systems that require heavier communication loads than single request/response cycles. Its binary data format is far more efficient than RESTful text transfers, and the use of HTTP 2.0 decreases its need to reestablish connections to servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage1-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage1-2.png" alt="An overview of HTTP vs. gRPC" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An overview of HTTP vs. gRPC at a glance&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Check out the examples in our &lt;a href="https://www.postman.com/devrel/workspace/public-grpc-apis" rel="noopener noreferrer"&gt;Public gRPC APIs workspace&lt;/a&gt;, and search the Postman Public API Network for others—we’ll be sure to highlight more and more of them in the future! We welcome your feedback and contribution as well, so if you find a great public-facing gRPC API, please make a pull request to our workspace.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Technical review by&lt;/em&gt; &lt;a href="https://blog.postman.com/author/joyce/" rel="noopener noreferrer"&gt;&lt;em&gt;Joyce Lin&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.postman.com/how-to-choose-http-or-grpc-for-your-next-api/" rel="noopener noreferrer"&gt;How to Choose HTTP or gRPC for Your Next API&lt;/a&gt; appeared first on &lt;a href="https://blog.postman.com" rel="noopener noreferrer"&gt;Postman Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>postman</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to Test JSON Properties in Postman</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Mon, 23 May 2022 17:09:28 +0000</pubDate>
      <link>https://dev.to/postman/how-to-test-json-properties-in-postman-2o02</link>
      <guid>https://dev.to/postman/how-to-test-json-properties-in-postman-2o02</guid>
      <description>&lt;p&gt;(This article was originally written by Vikram Sahu with technical review by Ian Douglas)&lt;/p&gt;

&lt;p&gt;JSON (JavaScript Object Notation) is one of the most used formats for sending and receiving API responses. With the rise of REST APIs, the JSON format has started gaining popularity among technologists. XML had similar popularity and usage, but that popularity has dropped over time with the adoption of JSON among tech communities.&lt;/p&gt;

&lt;p&gt;In this article, we’ll walk through an overview of JSON architecture, structure, and its examples. Then, we’ll check out some code snippets that will help us access and test JSON properties with Postman.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON architecture
&lt;/h2&gt;

&lt;p&gt;JSON is a text-based data format that’s used to represent data in a structured way based on JavaScript object syntax. As said earlier, it’s the most commonly used format for data exchange between two different machines running at two different locations geographically, or it can be the two applications running on the same machine.&lt;/p&gt;

&lt;p&gt;Though it’s very close to JavaScript object syntax, it can be independently used with different programming languages. Due to its popularity and human-readable standards, most programming languages have started supporting the JSON format within their pre-built libraries, which helps users to create or parse JSON data.&lt;/p&gt;

&lt;p&gt;JSON data can be easily stored in a file with a file extension called &lt;code&gt;.json&lt;/code&gt; and &lt;a href="https://stackoverflow.com/a/3828381/10232486" rel="noopener noreferrer"&gt;MIME type&lt;/a&gt; as &lt;code&gt;application/json&lt;/code&gt;. JSON supports the two most used data structures, arrays and objects. Since these data structures are foundational pillars of modern programming language, JSON is strong and useful data-exchange format.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON structure
&lt;/h2&gt;

&lt;p&gt;As described above, JSON structure is generated using arrays and objects. This means almost all the basic data structures like strings, numbers, boolean, and other object literals are also supported in the JSON format, making it easier for users to read, manage, build, and test the data with their other software programs. Since JSON is human-readable, it allows the user to generate simple to complex datasets without many efforts.&lt;/p&gt;

&lt;p&gt;For example, the simplest dataset can be an object starting with &lt;code&gt;{&lt;/code&gt; and ending with &lt;code&gt;}&lt;/code&gt; chaving a key/values pair where keys are name, email id, Twitter, GitHub handle and values are as shown in the object below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "email": "heyjson@example.com",
   "name": "JSON",
   "twitter": "@callmeJSON007",
   "github": "helloworldjsonhere"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the complex dataset can be a combination of objects and arrays, as shown below. The complexity of structure can be increased as per the requirement and accessibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "items": [
       {
           "orderID": "0000001211",
           "orderInvoiceNo": "1234567",
           "OrderBlocks": [
               {
                   "lineNo": [1,4,6,8,9,1,4],
                   "ProductCode": "#31451"
               },
               {
                   "lineNo": 2,
                   "ProductCode": "#64311"
               },
               {
                   "lineNo": 3,
                   "ProductCode": "#85959"
               }
           ]
       },
       {
           "orderID": "0000001212",
           "orderInvoiceNo": "1234568",
           "OrderBlocks": [
               {
                   "lineNo": 7,
                   "ProductCode": "#86869"
               },
               {
                   "lineNo": [6,7,4,8,4,2],
                   "ProductCode": "#10384"
               },
               {
                   "lineNo": 12,
                   "ProductCode": "#00873"
               }
           ]
       },
       {
           "orderID": "0000001213",
           "orderInvoiceNo": "1234569",
           "OrderBlocks": [
               {
                   "lineNo": 76,
                   "ProductCode": "#22291"
               }
           ]
       }
   ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, as you can see, even though the JSON is big and has multiple nested arrays and objects, it can be read with the same methods as the dataset that we describe above. That’s the magic of JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test and access JSON properties
&lt;/h2&gt;

&lt;p&gt;As we now know about JSON and how it can be created, let’s check a few code snippets which are commonly asked among different communities, and we’ll access keys and values within the JSON.&lt;/p&gt;

&lt;p&gt;To make it convenient and quick, you can fork the following Postman collection or click on the Run in Postman button below.&lt;/p&gt;

&lt;p&gt;Let’s walk through a few examples, where we’ll be using code that uses the &lt;code&gt;pm&lt;/code&gt; library to run the &lt;code&gt;test&lt;/code&gt; method. The text string will appear in the test output. The function inside the test represents an assertion as given below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.postman.com/postman/workspace/postman-answers/request/18070393-114a455a-50fc-4cbc-ada3-fb4629d19384" rel="noopener noreferrer"&gt;An array of all properties in an array of object&lt;/a&gt;: In this example, we’ll have an API response body as &lt;code&gt;jsonData&lt;/code&gt; and a code snippet showing how to access array properties within an array of object. API response body:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "data": {
       "items": [
           {
               "orderID": "0000001211",
               "orderInvoiceNo": "1234567",
               "OrderBlocks": [
                   {
                       "lineNo": 1,
                       "productCode": "001"
                   },
                   {
                       "lineNo": 2,
                       "productCode": "012"
                   },
                   {
                       "lineNo": 3,
                       "productCode": "013"
                   },
                   {
                       "lineNo": 4,
                       "productCode": "014"
                   }
               ]
           }
       ]
   }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code snippet to get all the properties of objects within an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm.test("array of all properties", () =&amp;gt; {
   //get data from API in jsonData
   let jsonData = pm.response.json()
   arrayOfObject = jsonData.data.items[0].OrderBlocks;

   //method 1
   let resIdData = arrayOfObject.map(a =&amp;gt; a.lineNo);
   console.log("values of lineNo in array : " + resIdData)

   //method 2
   let resProductCode = arrayOfObject.map(({ productCode }) =&amp;gt; productCode);
   console.log("values of productCode in array : " + resProductCode)

});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.postman.com/postman/workspace/postman-answers/request/18070393-9ff582e8-0840-4470-a8bb-e5181ec4661b" rel="noopener noreferrer"&gt;(Find) Array item by property&lt;/a&gt;: In this example, we’ll walk through the response body where we will find array items using JavaScript’s &lt;strong&gt;find&lt;/strong&gt; function, which scans the array and returns the object or value similar to the search term.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "data": {
       "items": [
           {
               "orderID": "0000001211",
               "orderInvoiceNo": "1234567",
               "OrderBlocks": [
                   {
                       "lineNo": 1,
                       "productCode": "001"
                   },
                   {
                       "lineNo": 2,
                       "productCode": "012"
                   },
                   {
                       "lineNo": 3,
                       "productCode": "013"
                   }
               ]
           }
       ]
   }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code snippet that search for object having value “3”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm.test("array of all properties", () =&amp;gt; {

   let jsonData = pm.response.json()
   arrayOfObject = jsonData.data.items[0].OrderBlocks;

   // You can use the arrow function expression:
   var result = arrayOfObject.find(obj =&amp;gt; {
       // Returns the object where
       // the given property has some value
       return obj.lineNo === 3
   })
   console.log(result)
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.postman.com/postman/workspace/postman-answers/request/18070393-f91145a2-c67c-46b5-85c7-9e660d8e770e" rel="noopener noreferrer"&gt;Arrays inside array of objects&lt;/a&gt;: In this example, we’ll access the values which are within an array of objects. API response body:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "data": {
       "items": [
           {
               "orderID": "0000001211",
               "orderInvoiceNo": "1234567",
               "OrderBlocks": [
                   {
                       "lineNo": [
                           1,
                           3,
                           4,
                           5
                       ],
                       "productCode": "001"
                   },
                   {
                       "lineNo": [
                           0,
                           6,
                           2,
                           5
                       ],
                       "productCode": "012"
                   }
               ]
           }
       ]
   }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm.test("array of all properties", () =&amp;gt; {
   let jsonData = pm.response.json()
   arrayOfObject = jsonData.data.items[0].OrderBlocks;

   //Accessing Array within array
   var arrWithinArr = arrayOfObject.map(o =&amp;gt; o.lineNo)
   console.log(arrWithinArr)

   //optional code, if you want to concat all results
   //Concating all the array retrieved from arrayOfObject
   const concatAllArrays = [].concat(...arrWithinArr)
   console.log(concatAllArrays)
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We’ve just gone through a conceptual overview of the JSON data format and how it gained its popularity when XML was high in its time. After looking at the similarities and differences between parsing and generating simple versus complex JSON datasets, hopefully you now know how to access and test JSON properties with Postman.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.postman.com/how-to-test-json-properties-in-postman/" rel="noopener noreferrer"&gt;How to Test JSON Properties in Postman&lt;/a&gt; appeared first on &lt;a href="https://blog.postman.com" rel="noopener noreferrer"&gt;Postman Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>When and How to Use JSON Serialization in Postman</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Wed, 09 Mar 2022 18:58:57 +0000</pubDate>
      <link>https://dev.to/postman/when-and-how-to-use-json-serialization-in-postman-4bfi</link>
      <guid>https://dev.to/postman/when-and-how-to-use-json-serialization-in-postman-4bfi</guid>
      <description>&lt;p&gt;As a new member of Postman’s developer advocacy team, I was recently tasked with completing our &lt;a href="https://www.postman.com/postman/workspace/30-days-of-postman-for-developers/overview" rel="noopener noreferrer"&gt;30 Days of Postman challenge&lt;/a&gt;. This challenge is a wonderful walk-through of the &lt;a href="https://blog.postman.com/new-postman-api-platform-redefining-api-management-for-api-first-world/" rel="noopener noreferrer"&gt;Postman API Platform&lt;/a&gt;’s main features, and it really helps you get familiarized with the many ways Postman is able to assist with your productivity.&lt;/p&gt;

&lt;p&gt;I started livestreaming &lt;a href="https://www.twitch.tv/ian_the_postmanaut" rel="noopener noreferrer"&gt;my journey on Twitch&lt;/a&gt;, and early on I was curious why I needed to serialize data in memory variables to pass between requests, especially when building dynamic request bodies. When I examined the data in the &lt;a href="https://blog.postman.com/powerful-debugging-with-the-postman-console/" rel="noopener noreferrer"&gt;Postman Console&lt;/a&gt;, it &lt;em&gt;appeared&lt;/em&gt; that they were being stored in a JSON object, yet I was unable to access the values correctly on subsequent requests.&lt;/p&gt;

&lt;p&gt;For viewers of &lt;a href="https://www.youtube.com/watch?v=iCiwIRvaZuA" rel="noopener noreferrer"&gt;my Postman Blindfold Challenge&lt;/a&gt;, we all learned that I &lt;em&gt;love&lt;/em&gt; to peel back the layers on what’s really going on inside a system. I have a background in development, specifically systems architecture, and so understanding how things communicate is something that greatly enhances my learning.&lt;/p&gt;

&lt;p&gt;Let’s do a quick review of serialization and why it’s used, and then look into Postman a little deeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is serialization?
&lt;/h2&gt;

&lt;p&gt;“Serializing” data is used to store and convert complex data types when writing and reading from memory. It is especially useful when sharing data between multiple systems which may not all share common data types. By turning these complex data structures into simpler types, it allows independent systems to convert data in ways that are agreed upon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2FSerialization-image-1-1000x641.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2FSerialization-image-1-1000x641.png" alt="A variable is given to the serializer, and turned into a string" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A variable is given to the serializer and turned into a string&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A simple example is an array of numbers. When we serialize this data into a string, in this JavaScript example with &lt;code&gt;JSON.stringify()&lt;/code&gt;, we can see how it is converted into a string that includes square brackets around our comma-delimited list of numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let arrayOfNumbers = [1,2,3,4,5]

JSON.stringify(arrayOfNumbers)

// ‘[1,2,3,4,5]’

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we “deserialize” this data back into an array, we are reversing the process to convert a string into what our programming language will interpret as an array of simple integer types. In this example, we’re still using JavaScript, and calling &lt;code&gt;JSON.parse()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2FSerialization-image-2-1000x588.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2FSerialization-image-2-1000x588.png" alt="A string is given to the deserializer and turned back into a complex data stype" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A string is given to the deserializer and turned back into a complex data type&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let stringData = “[1,2,3,4,5]”

JSON.parse(stringData)

// [1, 2, 3, 4, 5]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most programming languages will interpret simple data types, sometimes called “primitives,” in a straightforward way. These primitive data types include strings, numbers, boolean true/false, and then “unknown” types such as “undefined” or “null” values.&lt;/p&gt;

&lt;p&gt;If you need to store data in a more complex way—such as an array, or a deeply nested object—then transporting that data from one place to another is more easily managed between systems if we serialize the data.&lt;/p&gt;

&lt;p&gt;In fact, most APIs are already serializing data for us. The most common way that APIs will “package” their data right now is by using JavaScript Object Notation, or JSON, and sending it as a big string within the HTTP response body. This allows the sending system to transport data to your client software in a way that is a high-level, abstracted form of their data. Once you receive that JSON data, your application will need to convert that string back into a structure that it can interact with in a more natural way.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you should serialize your data in Postman
&lt;/h2&gt;

&lt;p&gt;So why is it that we need to JSON-serialize our data some of the time, and not all the time?&lt;/p&gt;

&lt;p&gt;As mentioned above, primitive types such as strings and numbers do not need to be serialized; only complex data types like arrays and objects will need serialization when saving them in variables. This applies not only to global and environment variables, but collection and local variables as well.&lt;/p&gt;

&lt;p&gt;If you need to prepare a response and &lt;a href="https://www.postman.com/postman/workspace/postman-answers/documentation/9215231-b9133e48-73c3-4aa4-b189-e038ee4c5e00" rel="noopener noreferrer"&gt;send it in a “dynamic body”&lt;/a&gt;, you will need to serialize the data and make sure that your body data is set to “raw,” and can be set to either “Text” or “JSON” in the dropdown at the end of that row of options:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2Fserialization-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2Fserialization-1.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is worth noting, also, that setting the outgoing body to “JSON” here does not have any effect on the dynamic variable you build in your pre-request script. Setting the body to JSON instead of Text only manipulates the outgoing header, not the body content itself.&lt;/p&gt;

&lt;p&gt;Trying to debug this with the Postman Console gets a little tricky, though. Logging is run at the same time the script is executed, so building a complex structure of data is going to show up in the console correctly. But the pre-request script and the building of the dynamic body are handled in two different places.&lt;/p&gt;

&lt;p&gt;If we do not serialize the data that we build, we’ll notice that Postman will convert this to a string containing &lt;code&gt;[object Object]&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2Fserialization-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2Fserialization-2.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, when we serialize this data using &lt;code&gt;JSON.stringify()&lt;/code&gt;, we see that our data is interpreted properly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2Fserialization-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.postman.com%2Fwp-content%2Fuploads%2F2022%2F03%2Fserialization-3.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code and testing was done using the &lt;a href="https://learning.postman.com/docs/developer/echo-api/" rel="noopener noreferrer"&gt;Postman Echo API&lt;/a&gt;, which echos back any data that you send to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this a necessary step?
&lt;/h2&gt;

&lt;p&gt;Building dynamic bodies for outgoing requests in Postman’s “pre-request scripts” is one of the most common places you will use this serialization technique.&lt;/p&gt;

&lt;p&gt;Another common time to serialize and deserialize your data is when sharing responses from one request to another request. When these API responses are more complex objects, serialization will convert this data into string format, which can be parsed before using it in another request. When you serialize and “persist” data from collections and environments to Postman’s servers, your team can use that data once they have deserialized the data using &lt;code&gt;JSON.parse()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Again, this serialization step is only necessary if you need to store and retrieve complex data types in collection or global variables, or save something (“persisting” the data) in your Postman environment.&lt;/p&gt;

&lt;p&gt;But why? Postman builds and stores this variable for use between portions of the application, and may execute code and build things in an order or manner that you are not expecting. Postman does its own serialization of the data, since we cannot know what you intend to do with your data. By using &lt;code&gt;JSON.stringify()&lt;/code&gt; and &lt;code&gt;JSON.parse()&lt;/code&gt; yourself, you help Postman to store and interpret the data more easily, removing unexpected results in your application.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Technical review by &lt;a href="https://blog.postman.com/author/arlemi/" rel="noopener noreferrer"&gt;Arlemi Turpault&lt;/a&gt; and &lt;a href="https://blog.postman.com/author/shamasis/" rel="noopener noreferrer"&gt;Shamasis Bhattacharya&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.postman.com/when-and-how-to-use-json-serialization-in-postman/" rel="noopener noreferrer"&gt;When and How to Use JSON Serialization in Postman&lt;/a&gt; appeared first on &lt;a href="https://blog.postman.com" rel="noopener noreferrer"&gt;Postman Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>tutorial</category>
      <category>datascience</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Effective Company Research tips before your next Technical Interview</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Tue, 27 Jul 2021 19:18:10 +0000</pubDate>
      <link>https://dev.to/iandouglas/effective-company-research-tips-before-your-next-technical-interview-ahj</link>
      <guid>https://dev.to/iandouglas/effective-company-research-tips-before-your-next-technical-interview-ahj</guid>
      <description>&lt;p&gt;aka "hack the networking/outreach"&lt;/p&gt;

&lt;p&gt;I'm the author of &lt;a href="https://techinterview.guide" rel="noopener noreferrer"&gt;https://techinterview.guide&lt;/a&gt; and I live-stream twice a week on Sundays and Thursdays about technical interview preparation.&lt;/p&gt;

&lt;p&gt;A few weeks ago, I made a video about &lt;a href="https://youtu.be/eqMlwEerw3Y?t=317" rel="noopener noreferrer"&gt;how to research industries and companies&lt;/a&gt; where you might like to work. It showcased some of my favorite tips on the topic.&lt;/p&gt;

&lt;p&gt;There are lots of tools out there to use for tracking your application status when you apply for jobs. Some of them allow you to add custom notes, etc..&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;I use Google Sheets to track a list of things which are important to me about a company. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;company name&lt;/li&gt;
&lt;li&gt;your application status&lt;/li&gt;
&lt;li&gt;next step in the process&lt;/li&gt;
&lt;li&gt;primary contact at the company&lt;/li&gt;
&lt;li&gt;where are they located&lt;/li&gt;
&lt;li&gt;do they allow remote work&lt;/li&gt;
&lt;li&gt;what are the primary technologies they use&lt;/li&gt;
&lt;li&gt;what's the dress code&lt;/li&gt;
&lt;li&gt;what is the typical salary range for a role here&lt;/li&gt;
&lt;li&gt;how big is the company&lt;/li&gt;
&lt;li&gt;how big is the engineering team compared to the rest of the company&lt;/li&gt;
&lt;li&gt;do they publish DEI stats&lt;/li&gt;
&lt;li&gt;company blog URL&lt;/li&gt;
&lt;li&gt;primary company values&lt;/li&gt;
&lt;li&gt;top customers&lt;/li&gt;
&lt;li&gt;top competition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Place this column on tab number 1 at the bottom of Google Sheets. &lt;strong&gt;Rename this tab "criteria".&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can add whichever kinds of items are important to you. For example, it might be important to you to know if the office is pet-friendly. Maybe you love taking an office pet for a quick walk, OR maybe you have allergies and cannot attend work at an office when a pet is present.&lt;/p&gt;

&lt;p&gt;Finally, I like to add criteria at the bottom of my list that indicates the head of HR, the head of Engineering, and any contacts that my connections on LinkedIn might know. We'll talk about this later regarding cover letters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rank these Criteria
&lt;/h2&gt;

&lt;p&gt;Your list of criteria will be different than mine. How you prioritize them will also be different than myself.&lt;/p&gt;

&lt;p&gt;Place the criteria that is most important to you at the top of the list, and the less-important criteria at the bottom.&lt;/p&gt;

&lt;p&gt;If you think of additional criteria as you do company research, add it to this list.&lt;/p&gt;

&lt;p&gt;Next, organize the things on a regular basis. Your criteria may shift over time, and that's okay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make a new tab per Industry
&lt;/h2&gt;

&lt;p&gt;Make a new tab at the bottom of the spreadsheet. Rename it to an industry that is important to you. For example, maybe "fitness" or "environment" or "travel".&lt;/p&gt;

&lt;p&gt;In that new tab, you're going to create a reference to the "criteria" column and put those references in this tab.&lt;/p&gt;

&lt;p&gt;In row/column A1, enter the following formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=criteria!A1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy that cell (Cmd-C or Ctrl-C), highlight all cells from A1 through A25 (or however many you want), and Paste (Cmd-V or Ctrl-V) the cell you copied.&lt;/p&gt;

&lt;p&gt;You should now see a linked copy of the cells from your "criteria" tab on this sheet.&lt;/p&gt;

&lt;p&gt;As you add new criteria on the "criteria" tab, you should see them show up on this tab as well. Note that you may need to copy additional rows if you add more criteria.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Up: the actual research
&lt;/h2&gt;

&lt;p&gt;In each new tab you create, such as "fitness" or "fintech" or whatever, you can now add each company in column B, column C, column D, etc.&lt;/p&gt;

&lt;p&gt;You might ask yourself ... "self -- how do I actually fill in this grid of information?" I'm glad you asked!&lt;/p&gt;

&lt;p&gt;LinkedIn is a great resource, and there are many others such as GlassDoor, StackShare and others where you can find information about a company.&lt;/p&gt;

&lt;p&gt;If, in the process of researching a company you also find competition for that company, add THEM as a column in your spreadsheet as well! If you don't interview at the first company, you might get an interview at their competition!&lt;/p&gt;

&lt;p&gt;Fill in as much detail as you can find. &lt;strong&gt;It's okay if you can't find certain pieces of information. We're getting to that.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  "Is This Okay With Me?"
&lt;/h2&gt;

&lt;p&gt;While you fill in this spreadsheet, constantly ask yourself, "Is this okay with me?"&lt;/p&gt;

&lt;p&gt;Is it okay that you found this information? Do you like what you found? Was it easy to find? Does it make sense to you?&lt;/p&gt;

&lt;p&gt;If you CANNOT find information for a specific criteria, also ask yourself "is THAT okay with me that I could NOT find that information?" Was it hard to find, could you find it at all? &lt;/p&gt;

&lt;p&gt;If something is important to you and you cannot find information, it's not a show-stopper.&lt;/p&gt;

&lt;p&gt;But it's important to do this check whenever you do research. For example, I never want a job where I have to wear a shirt and tie every day.&lt;/p&gt;

&lt;p&gt;If I found out that a particluar job was formal enough to require wearing a tie, I would seriously think twice before applying. That's just a strong personal preference. But so is working for a company who has "Big Tobacco" as a client. It's against my morals to support that industry, and so knowing who a company's client list is is also important to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fill in the Gaps
&lt;/h2&gt;

&lt;p&gt;Now that you've researched as much as possible, you'll notice that you still have gaps in information.&lt;/p&gt;

&lt;p&gt;This is where networking and outreach becomes critical.&lt;/p&gt;

&lt;p&gt;Through LinkedIn, you can find a company, get a list of their employees. Keep in mind these are people who volunteer this information on LinkedIn and may be out of date.&lt;/p&gt;

&lt;p&gt;Find a peer-level employee on that list. If you're an entry-level developer, find another entry-level developer. If you're a senior developer, find another senior developer, and so on.&lt;/p&gt;

&lt;p&gt;Connect with them. Let them know in the connection request that you have specific questions you'd like to ask them about the company. Don't just click on the "connect" button -- send a request with a message like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hi Ian. I see that you work at Acme Inc. I'm doing some research on the company and would like to get to know a peer at the business. I have some specific questions about the company, and wondered if you had some time to chat. I'm happy to send the questions to you ahead of time or chat asynchronously if that's more convenient.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you connect with an employee there, now you have SPECIFIC questions to ask: all those gaps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I wasn't able to easily find any information about ___, and I was wondering if you could help me find that, or tell me about that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can also ask them to confirm information you DID find:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I noticed on LinkedIn that the company size was about __ employees. Is that still accurate? Could you guess at the percentage of employees that make up the engineering team?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you're asking very sepcific questions, getting specific answers.&lt;/p&gt;

&lt;p&gt;And the whole time, keep asking yourself &lt;strong&gt;"is this okay with me?"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Contacts
&lt;/h2&gt;

&lt;p&gt;While you're connecting with people at these companies, ask them for the names of the head of HR, or the head of Engineering if the company is small. Most businesses under 40 people may not even have an HR department yet, but most companies near 50 employees will have an established HR team.&lt;/p&gt;

&lt;p&gt;If they have an HR team, you will address your cover letter and application to that person. If they do not have an HR team, you will address your cover letter to the VP of Engineering or a Director of Engineering. Typically, a CTO is a last resort as a CTO is really in charge of projects and technologies at a company, where a VP of Engineering will be in charge of hiring and people management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now you can apply for that job
&lt;/h2&gt;

&lt;p&gt;In your cover letter you can mention that you've been speaking with someone in the company (mention them by name &lt;strong&gt;only if they give you their permission&lt;/strong&gt;). Mention the research you've been doing, this will be a tremendous benefit to your job search.&lt;/p&gt;

&lt;p&gt;Good luck in your job hunt!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow for more!
&lt;/h2&gt;

&lt;p&gt;I stream on &lt;a href="https://techinterview.guide/streaming" rel="noopener noreferrer"&gt;Twitch on Sundays and Thursdays&lt;/a&gt;, and you can subscribe to &lt;a href="https://youtube.com/c/iandouglas" rel="noopener noreferrer"&gt;my YouTube channel&lt;/a&gt; to get notified of new videos.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>outreach</category>
      <category>research</category>
      <category>interviewing</category>
    </item>
    <item>
      <title>How to shortcut the Leetcode grind</title>
      <dc:creator>W Ian Douglas</dc:creator>
      <pubDate>Mon, 26 Jul 2021 22:02:00 +0000</pubDate>
      <link>https://dev.to/iandouglas/how-to-shortcut-the-leetcode-grind-5975</link>
      <guid>https://dev.to/iandouglas/how-to-shortcut-the-leetcode-grind-5975</guid>
      <description>&lt;p&gt;I'm a professional technical interview coach, and Leetcode-style interviews aren't going away any time soon. There IS a way to shortcut the process of grinding hundreds upon hundreds of challenges. Here are my favorite tips.&lt;/p&gt;

&lt;p&gt;I outline a lot of notes and ideas &lt;a href="https://youtu.be/QT0dS9C9uwo?t=252" rel="noopener noreferrer"&gt;in a 90-minute YouTube video on the subject&lt;/a&gt;, but wanted to write them up here as well to help others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step One: Practice lots of Mock Interviews
&lt;/h2&gt;

&lt;p&gt;There are good platforms out there such as &lt;a href="https://iio.sh/r/F2NJ" rel="noopener noreferrer"&gt;intervieiwng.io&lt;/a&gt; and &lt;a href="https://www.pramp.com/promo/iandouglas" rel="noopener noreferrer"&gt;Pramp&lt;/a&gt;. For disclosure, I'm an interviewer on IIO, and my promo code for Pramp was in exchange for &lt;a href="https://blog.pramp.com/the-interviewers-perspective-how-to-answer-why-should-i-hire-you-ad070987c2cc" rel="noopener noreferrer"&gt;some blogging I did on their platform&lt;/a&gt; a few years ago.&lt;/p&gt;

&lt;p&gt;Without a good coach, it's hard to get better. Grinding on leetcode problems won't tell you what you're doing well, or things to improve, unless someone can guide you along the way.&lt;/p&gt;

&lt;p&gt;Get on a platform where you can be given some direct feedback on what you're doing well and where you need to improve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Two: Come up with a good Pseudocode Process
&lt;/h2&gt;

&lt;p&gt;Nver jump straight into coding when given a technical challenge. Always break the problem down into smaller pieces to solve, and ask clarifying questions along the way.&lt;/p&gt;

&lt;p&gt;Pseudocode should be written like a food recipe:&lt;/p&gt;

&lt;p&gt;"crack an egg in a bowl"&lt;/p&gt;

&lt;p&gt;I'm not telling you how to crack the egg, where to tap the egg, how to hold the egg, how hard to tap the egg. I'm going to presume that (a) you know how to crack an egg, and (b) through your own experience you know the best way to crack the egg for this kind of recipe.&lt;/p&gt;

&lt;p&gt;By keeping the pseudocode really high-level in this fashion, you're not locking yourself into an implementation. If you write down "for loop over the array" then you've locked yourself into an implementation to strictly use a "for" loop.&lt;/p&gt;

&lt;p&gt;Your pseudocode should be flexible enough to give you the ability to change your mind on "how". As an interviewer, I can ask questions about how you MIGHT implement something, but your steps should remain high level.&lt;/p&gt;

&lt;p&gt;Start vague, add more detail, but if you've added so much detail that you've locked in your implementation, you might want to back up a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Three: Learn from Others
&lt;/h2&gt;

&lt;p&gt;Okay, leetcode.com. I appreciate their platform more than others because of the discussion forum for each problem, and because they give you actionable feedback when you run your code to see what didn't work based on inputs and expected output and actual output.&lt;/p&gt;

&lt;h3&gt;
  
  
  3a -- find a category of problem to study
&lt;/h3&gt;

&lt;p&gt;Next, we're going to use Sean Prashad's awesome &lt;a href="https://seanprashad.com/leetcode-patterns/" rel="noopener noreferrer"&gt;Leetcode Patterns site&lt;/a&gt;. From here we're going to pick any category of problem, say "DFS" (Depth First Search), and then pick any of those problems at random.&lt;/p&gt;

&lt;p&gt;From here we'll visit the discussion forum for that problem -- the link will usually look like "Discuss (999+)".&lt;/p&gt;

&lt;h3&gt;
  
  
  3b -- find 4 to 5 answers in programming languages you DO NOT KNOW
&lt;/h3&gt;

&lt;p&gt;By using languages you don't know it will force you into higher-level thinking like "okay, they're passing a parameter called 'menu', and I see they're doing a 'for' loop with that parameter, so I'm going to write down 'loop over menu' as my instruction."&lt;/p&gt;

&lt;p&gt;If you look at an answer in a language you DO know, you can certainly write down your pseducodeo quicker because you'll have a better idea what's happening, but you're (a) more likely to lock yourself into an implementation, and (b) more likely to memorize the SYNTAX, where we're here to learn the STRATEGY.&lt;/p&gt;

&lt;h3&gt;
  
  
  3c -- compare the pseudocode
&lt;/h3&gt;

&lt;p&gt;Once you have pseudocode written out for 4 or 5 answers, compare them side by side. Highlight lines that are similar, and try to come up with a 4 to 6 line algorithm from there.&lt;/p&gt;

&lt;p&gt;For example, if you were solving a maze, the algorithm might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;work until you get to an intersection
from a list of possible directions
  go in that direction
  repeat/recurse all of the above
  rewind to previous intersection if that didn't work
if we're at the exit, we're done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3d -- write it on a Post-It note, stick it on your monitor
&lt;/h3&gt;

&lt;p&gt;Study these often.&lt;/p&gt;

&lt;p&gt;The next time you try a problem of this type, see whether that algorithm will work. If not, repeat step 3 for that new kind of problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Four: Build a workout Schedule
&lt;/h2&gt;

&lt;p&gt;Now that you have a condensed list of study notes, you can form a plan for studying different kinds of problems every day.&lt;/p&gt;

&lt;p&gt;Research shows that repeating something 2 days later and 3 days later is optimal for long-term memory. PROVIDED that you start over from nothing. Don't review old notes, don't review pseudocode, start all over again.&lt;/p&gt;

&lt;p&gt;Come up with a calendar where you try a new kind of problem every day, and then sprinkle in when you can repeat a previous problem.&lt;/p&gt;

&lt;p&gt;I give some examples of this in my YouTube video &lt;a href="https://youtu.be/QT0dS9C9uwo?t=2870" rel="noopener noreferrer"&gt;around the 48-minute mark&lt;/a&gt;, but could look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sun: DFS-1
Mon: Heap-1
Tue: BFS-1, repeat DFS-1
Wed: DP-1, repeat Heap-1
Thu: DFS-2, repeat BFS-1
Fri: Array-1, repeat DP-1, repeat DFS-1
Sat: break day

Sun: F&amp;amp;S Ptr, repeat DFS-2, repeat DP-1
Mon: etc etc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have two DFS problems on this schedule because maybe the company where I'm interviewing is more likely to ask DFS-style questions.&lt;/p&gt;

&lt;p&gt;I describe the "break day" in the video. It's important to let our brain rest, and to take time to just analyze problems for the "type" of problem it may be. This will help you more quickly identify a leetcode-type challenge in a real interview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To sum it all up: practicing mock interviews with someone else is the best way to get feedback. Without feedback you're not going to get better as quickly.&lt;/p&gt;

&lt;p&gt;Next, learn the algorithms by studying how other people have solved particular kinds of challenges. Condense them into very concise steps, and study those.&lt;/p&gt;

&lt;p&gt;Finally, come up with a regular schedule for studying different kinds of problems every day, and repeating them. Add the same kind of problem in the mix more often if you think the company is more likely to ask that kind of problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclosures
&lt;/h2&gt;

&lt;p&gt;I stream &lt;a href="https://techinterview.guide/streaming" rel="noopener noreferrer"&gt;every Sunday and Thursday on Twitch&lt;/a&gt; around topics of technical interview prep. Come by and check out the stream, chat and say hello and ask questions. I also do live resume reviews on Sundays. The link above will give you all of the info you need.&lt;/p&gt;

</description>
      <category>interviewing</category>
      <category>leetcode</category>
      <category>coaching</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
