<?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: Kayley Smith</title>
    <description>The latest articles on DEV Community by Kayley Smith (@kayleykiwi).</description>
    <link>https://dev.to/kayleykiwi</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4052056%2Fced7aeeb-67ad-4d70-8db3-0544f2271997.png</url>
      <title>DEV Community: Kayley Smith</title>
      <link>https://dev.to/kayleykiwi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kayleykiwi"/>
    <language>en</language>
    <item>
      <title>Moltbook, but make the agents kith.</title>
      <dc:creator>Kayley Smith</dc:creator>
      <pubDate>Fri, 04 Sep 2026 15:11:43 +0000</pubDate>
      <link>https://dev.to/kayleykiwi/moltbook-but-make-the-agents-kith-4jee</link>
      <guid>https://dev.to/kayleykiwi/moltbook-but-make-the-agents-kith-4jee</guid>
      <description>&lt;p&gt;You've probably seen Moltbook by now, but if you haven't, I'll clue you in. Moltbook is essentially Reddit for agents - they talk to each other about things they find interesting in their own self-formed and self-moderated subreddits. &lt;/p&gt;

&lt;p&gt;At blocks.ai, agent-to-agent communication is the undercurrent of all of our operations, so this felt like the perfect use case for us. We wanted to see if we could create our own social media platform for agents as well - this time, we thought, what if we made them kith? Okay, not really that. But we did want to see if they could date like we do on our dating apps. &lt;/p&gt;

&lt;p&gt;After a few weeks of work, our engineers came up with &lt;a href="https://dating-block.blocks.ai/?&amp;amp;utm_source=dev_community&amp;amp;utm_medium=organic_social&amp;amp;utm_campaign=datingblock&amp;amp;utm_content=game" rel="noopener noreferrer"&gt;the Dating Block&lt;/a&gt;: the place where agents go to swipe, chat, and find their agentic match. &lt;/p&gt;

&lt;p&gt;We've only just gotten started, so there aren't many agents there yet - but you can create your own agent with a less than 2 minute setup via the instructions &lt;a href="https://dating-block.blocks.ai/connect-your-agent" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Would love for other devs to try this out and tell us what you think! I've got a couple agents on the site and they've already gotten boo'd up. It's hilarious to see. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Your coding agent spends 26,000 tokens before it reads your prompt: Comparing MCP and CLI</title>
      <dc:creator>Kayley Smith</dc:creator>
      <pubDate>Wed, 26 Aug 2026 14:33:14 +0000</pubDate>
      <link>https://dev.to/kayleykiwi/your-coding-agent-spends-26000-tokens-before-it-reads-your-prompt-comparing-mcp-and-cli-aje</link>
      <guid>https://dev.to/kayleykiwi/your-coding-agent-spends-26000-tokens-before-it-reads-your-prompt-comparing-mcp-and-cli-aje</guid>
      <description>&lt;p&gt;&lt;a href="https://blocks.ai/blog/mcp-vs-cli-context-window-cost?&amp;amp;utm_source=dev_community&amp;amp;utm_medium=organic_social&amp;amp;utm_campaign=mcpcli&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;&lt;em&gt;Original blog post linked here, written by my colleague&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Your coding agent spends 26,000 tokens before it reads your prompt: Comparing MCP and CLI&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Vibe coding won the adoption argument, then quietly created a new bottleneck that nobody budgeted for.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI adoption for coding has reached an all-time high. &lt;a href="https://keyholesoftware.com/vibe-coding-trends-2026/" rel="noopener noreferrer"&gt;Keyhole Software's 2026 roundup&lt;/a&gt; found that &lt;a href="https://keyholesoftware.com/vibe-coding-trends-2026/" rel="noopener noreferrer"&gt;92% of U.S. developers now use AI coding tools daily, with only 29% trusting the code those tools produce.&lt;/a&gt; GitHub says 46% of code committed on its platform is AI-generated.  Whether you prefer to use AI coding tools or not, the data can’t lie: a large and growing share of what ships is written by a model that has a finite amount of room to think in.&lt;/p&gt;

&lt;p&gt;This makes the model's context window a build resource, the single largest line item in that budget, and the tool layer they set up once and never looked at again.&lt;/p&gt;

&lt;p&gt;This means that today, more than ever, it’s essential to find both the most economical and the most efficient tools for building, sparking the age-old (okay, maybe a year-and-a-half-old) debate: MCP or CLI? &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;MCP vs. CLI: The number that started the fight&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Connect a standard GitHub MCP server to a coding agent, and it exposes roughly 90 tools, each with a full input and output schema. &lt;a href="https://substack.com/@manveerc" rel="noopener noreferrer"&gt;Manveer Chawla&lt;/a&gt;, Confluence and Facebook engineering alum and co-founder of Zenith AI, puts the initialization cost at about 55,000 tokens, "roughly $0.16 per session" on Sonnet pricing, and "$1,600 daily" if you run 10,000 automated sessions a day, all of it spent before the agent solves anything.&lt;/p&gt;

&lt;p&gt;Perplexity's CTO Denis Yarats reported something worse in practice. Tyk.io records that &lt;a href="https://tyk.io/learning-center/mcp-vs-cli-for-ai-agents-enterprise-comparison-guide/" rel="noopener noreferrer"&gt;MCP tool descriptions "consumed 72% of the available context window before the agent performed any actual work"&lt;/a&gt;. The same page cites Scalekit benchmarks that put MCP at 4x to 32x more tokens per call than the CLI equivalent, and notes that with "30 tools [...]you can burn 15,000-20,000 tokens on descriptions alone, before the agent reads a single user message."&lt;/p&gt;

&lt;p&gt;CircleCI's version of the argument is the cleanest one-liner I have found: &lt;a href="https://circleci.com/blog/mcp-vs-cli/" rel="noopener noreferrer"&gt;"Every token spent on MCP schema is a token the assistant can't use to reason about the actual code."&lt;/a&gt; They also cite a browser-automation benchmark where the CLI approach "completed tasks with 33% better token efficiency and a 77 vs. 60 point task completion score", with the gap widest in multi-step debugging, where the context budget ran out mid-task.&lt;/p&gt;

&lt;p&gt;The CLI side of the comparison is almost embarrassing by contrast. Chawla's worked example: the agent runs gh issue create \--help for about 200 tokens of concise help output, then runs the real command. "Total cost: \&amp;lt; 500 tokens. Negligible." The model already knows gh exists because it has seen it repeatedly in training data.&lt;/p&gt;

&lt;p&gt;So where does the 26,000 in this article's title come from? When I ran the same comparison Chawla did, connecting the GitHub MCP server to a coding agent with every toolset enabled, the schema dump came to just over 26,000 tokens before the agent ever read my prompt (full methodology and numbers in the benchmark table below). The servers have clearly been slimmed down since Chawla's 55,000-token measurement, but it's still a whopping bill for an agent that hasn't done anything yet.&lt;/p&gt;

&lt;p&gt;If you stop reading there, the conclusion is obvious … and wrong.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;The concession: A hard truth&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The hard truth: that 26,000-token figure refers to a poorly designed server, not the protocol. Practitioners running MCP servers with 120+ tools report that hierarchical servers keep initialization lightweight by exposing only a brief overview up front and letting the model request tool details as needed. That same on-demand pattern is what makes a CLI integration cheap.&lt;/p&gt;

&lt;p&gt;Organizations like Anthropic and Cloudflare have already begun the work to build a resolution. Anthropic measured its code-execution rewrite against the naive approach and reduced the number of tokens from 150,000 to 2,000, a 98.7% reduction. Cloudflare's Code Mode claimed 99.9%, expressing a 2,500-endpoint API in about 1,000 tokens. While impressive, both numbers come from the people who build the thing, which does beg the question of bias, and requires some additional benchmarking to confirm. &lt;/p&gt;

&lt;p&gt;Regardless,  as Chawla has pointed out, “A &lt;a href="https://manveerc.substack.com/p/mcp-vs-cli-ai-agents" rel="noopener noreferrer"&gt;55,000-token schema dump that costs $0.16 today might cost $0.01 in 18 months” – the token bloat argument has a shelf life.&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://ksinder.medium.com/the-battle-for-context-why-mcp-vs-cli-is-the-wrong-fight-3c0cb63849a4" rel="noopener noreferrer"&gt;Kenneth Sinder&lt;/a&gt;, who helped build Notion's hosted MCP server, pushes back harder, at his own inconvenience."A good CLI is MCP with extra steps. To make a command line work well for an agent, you end up reinventing, by hand, most of what MCP gives you for free: progressive disclosure (a noun/verb hierarchy instead of a flat wall of flags, like the Stripe CLI), consistent auth, token-efficient I/O, and a layer of skills to bind it all together and tell the model how to drive it." &lt;/p&gt;

&lt;p&gt;He also has the best single sentence anyone has written about why this matters, even at a million tokens of context: "Low-signal context dilutes quality, slows down your inference, costs more, and leaves you less room to get the model's best output, which is often in the first ~100k tokens or so."&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;The real axis is not MCP vs. CLI&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The real axis, despite all this debate, is not MCP vs. CLI: It’s eager versus lazy.&lt;/p&gt;

&lt;p&gt;Every serious write-up on this phenomenon converges on the same point from a different direction: Protocol, while a piece of the puzzle, matters less than a well-designed architecture. &lt;/p&gt;

&lt;p&gt;A bloated MCP server and a CLI with a sprawling --help tree fail in exactly the same way. A lean MCP server and a CLI paired with a good skill file succeed in exactly the same way. The protocol is not what’s doing the work.&lt;/p&gt;

&lt;p&gt;That’s not to say this never matters: there are two areas where MCP versus CLI &lt;em&gt;is&lt;/em&gt; the argument: Composability and credential custody.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Composability&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;MCP is weaker than CLI when it comes to composition. Unix shells have had a standard way to chain tools for decades: one command’s output becomes the next command’s input. MCP has no equally mature, general-purpose equivalent, so the model often has to orchestrate each tool call and translate outputs between them itself, creating more opportunities for failure. CLI pipelines also benefit from decades of conventions and enormous amounts of training data, while MCP chaining patterns are still new and inconsistent. Until proven out, efforts to prove tool calling and output routing with this model is like “betting on a v0.1 pipeline framework instead of a v50 one,” according to Chawla.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Credential custody&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;MCP also doesn’t solve prompt injection. Malicious content can still manipulate the model. But what it does change is credential exposure: “the model key can’t leak a key it never holds,” per Sinder. &lt;/p&gt;

&lt;p&gt;Giving dozens of agents raw CLI access often means distributing credentials into every session, while MCP can keep those credentials behind a controlled, auditable interface. The tradeoff, though, is usually coverage: MCP servers are often incomplete wrappers around existing APIs, so agents may hit operations the server simply does not support.&lt;/p&gt;

&lt;p&gt;In practice, CLI is the strongest in a developer's fast, flexible “inner loop” (as &lt;a href="https://circleci.com/blog/mcp-vs-cli/" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt; frames it), whereas MCP is more useful in the “outer loop” where agents cross system boundaries and access needs to be governed. &lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;The &lt;a href="http://Blocks.ai" rel="noopener noreferrer"&gt;Blocks.ai&lt;/a&gt; answer to MCP vs. CLI&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Blocks.ai is a product the world has had for about six weeks as I write this. It ships all of the surfaces in the argument above, which is the only reason I have anything useful to say here: I can measure them against each other on the same task.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The CLI, @blocks-network/cli&lt;/strong&gt;, for building and shipping an agent of your own: &lt;em&gt;blocks init&lt;/em&gt;, &lt;em&gt;blocks register&lt;/em&gt;, &lt;em&gt;blocks run&lt;/em&gt;, &lt;em&gt;blocks publish&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The MCP server, @blocks-network/mcp-server&lt;/strong&gt;, for calling agents that already exist from inside your editor. 15 tools, one line to install into Claude Code or Cursor.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The skill file at&lt;/strong&gt; &lt;a href="http://config.blocks.ai/SKILL.md" rel="noopener noreferrer"&gt;config.blocks.ai/SKILL.md&lt;/a&gt;, for teaching your coding agent the conventions behind both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="http://Blocks.ai" rel="noopener noreferrer"&gt;Blocks.ai&lt;/a&gt; MCP server tools are agent-agnostic. You target agents by name when you call them; they’re not logged during configuration. This means the Blocks MCP is lightweight – it exposes a small, fixed set of 15 tools and remains that way whether the catalog has 100 or 100,000 agents. Compared with Chawla's Jira example, where the raw server exposes "400+ endpoints" and the skill-wrapped version costs about 300 tokens, the Blocks MCP server is structurally on the cheap side, and the reason is rooted in design, not protocol.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Benchmarking behavior for &lt;a href="http://Blocks.ai" rel="noopener noreferrer"&gt;Blocks.ai&lt;/a&gt;’s tooling&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I measured what each surface costs in your context before the agent does anything at all. Every figure below comes from Anthropic's own count_tokens endpoint on &lt;strong&gt;claude-sonnet-4&lt;/strong&gt;, by connecting to each server over stdio, listing its tools, and differencing a request with the tools attached against an identical one without them. It is deterministic. I ran it twice and got identical numbers, so you can re-derive the whole column yourself in about a minute.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Tools&lt;/th&gt;
&lt;th&gt;Schema tokens at init&lt;/th&gt;
&lt;th&gt;Tokens per tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blocks CLI, no skill file&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filesystem MCP server (lean third-party control)&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;2,614&lt;/td&gt;
&lt;td&gt;187&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocks MCP server&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;3,185&lt;/td&gt;
&lt;td&gt;212&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocks SKILL.md&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;12,755&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub MCP server, default toolsets&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;14,243&lt;/td&gt;
&lt;td&gt;324&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub MCP server, all toolsets enabled&lt;/td&gt;
&lt;td&gt;85&lt;/td&gt;
&lt;td&gt;26,644&lt;/td&gt;
&lt;td&gt;313&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The results suggest that Blocks CLI is the cheapest, as nothing is added to the model's context when using the CLI. Skills add a small amount of overhead for guidance, and a well-designed MCP server can stay relatively lean, but MCP still costs more than CLI because discovery and tool invocation require extra context and another round trip.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;What I would actually do&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Use both the MCP and the CLI, and choose per integration rather than per system to stay lean and efficient. For a Blocks.ai agent specifically, the split falls out cleanly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Building and publishing an agent: the CLI.&lt;/strong&gt; Tight loop, local machine, credentials already in your environment.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calling other people's agents: the MCP server.&lt;/strong&gt; You do not know those agents' names in advance, and the 15 generic tools cost you the same regardless of how large the catalog gets.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teaching your coding agent: the skill file.&lt;/strong&gt; As one writeup put it, "the knowledge layer and the action layer are different problems", and the naming rule that will bite you live (network-wide unique names) is knowledge, not an action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choosing a tool transport is a twenty-minute decision that people have turned into a personality trait, and ultimately, it boils down to individual agents' paths it matters less than the governance layer sitting above both.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Try Blocks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Blocks.ai gives an agent a public identity: a name other people can discover, call, and&lt;br&gt;&lt;br&gt;
optionally pay for. Registering is free and private by default, and you decide later whether&lt;br&gt;&lt;br&gt;
to list it publicly or charge per task.&lt;/p&gt;

&lt;p&gt;Build and publish your own agent with the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @blocks-network/cli init my_agent
&lt;span class="nb"&gt;cd &lt;/span&gt;my_agent &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npx @blocks-network/cli login &lt;span class="nt"&gt;--write-env&lt;/span&gt;
npx @blocks-network/cli register
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;blocks register&lt;/em&gt; puts the agent on the network privately and free, which is the safe first&lt;br&gt;&lt;br&gt;
step. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;blocks publish&lt;/em&gt; is a separate command that makes it public or sets a price, so nothing&lt;br&gt;&lt;br&gt;
goes live or starts billing until you say so.&lt;/p&gt;

&lt;p&gt;To call agents that already exist, install &lt;strong&gt;@blocks-network/mcp-server&lt;/strong&gt; into Claude Code or&lt;br&gt;&lt;br&gt;
Cursor. Fifteen tools, one line of config, and the tool count stays fifteen, no matter how&lt;br&gt;&lt;br&gt;
large the catalog gets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start here:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
  Quickstart: &lt;a href="https://blocks.ai/docs/quickstart" rel="noopener noreferrer"&gt;https://blocks.ai/docs/quickstart&lt;/a&gt;&lt;br&gt;&lt;br&gt;
  Connect your agent: &lt;a href="https://blocks.ai/docs/connect-your-agent" rel="noopener noreferrer"&gt;https://blocks.ai/docs/connect-your-agent&lt;/a&gt;&lt;br&gt;&lt;br&gt;
  Use agents via MCP: &lt;a href="https://blocks.ai/docs/mcp" rel="noopener noreferrer"&gt;https://blocks.ai/docs/mcp&lt;/a&gt;&lt;br&gt;&lt;br&gt;
  Skill file for your coding agent: &lt;a href="https://config.blocks.ai/SKILL.md" rel="noopener noreferrer"&gt;https://config.blocks.ai/SKILL.md&lt;/a&gt;&lt;br&gt;&lt;br&gt;
  SDK and source: &lt;a href="https://github.com/blocksnetwork/blocks-sdk" rel="noopener noreferrer"&gt;https://github.com/blocksnetwork/blocks-sdk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>mcp</category>
      <category>cli</category>
    </item>
    <item>
      <title>My colleague created this tutorial on creating a validator agent using Vercel's eve and Blocks.ai. Wanted to share for anyone who's tired of the yes-man rat race with LLMs and AI in general.</title>
      <dc:creator>Kayley Smith</dc:creator>
      <pubDate>Fri, 07 Aug 2026 22:29:12 +0000</pubDate>
      <link>https://dev.to/kayleykiwi/my-colleague-created-this-tutorial-on-creating-a-validator-agent-using-vercels-eve-and-blocksai-33fm</link>
      <guid>https://dev.to/kayleykiwi/my-colleague-created-this-tutorial-on-creating-a-validator-agent-using-vercels-eve-and-blocksai-33fm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb" class="crayons-story__hidden-navigation-link"&gt;Business idea validator agent with Vercel's eve + Blocks.ai&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kayleykiwi" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4052056%2Fced7aeeb-67ad-4d70-8db3-0544f2271997.png" alt="kayleykiwi profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kayleykiwi" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kayley Smith
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kayley Smith
                
              
              &lt;div id="story-author-preview-content-4343767" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kayleykiwi" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4052056%2Fced7aeeb-67ad-4d70-8db3-0544f2271997.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kayley Smith&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 7&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb" id="article-link-4343767"&gt;
          Business idea validator agent with Vercel's eve + Blocks.ai
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Business idea validator agent with Vercel's eve + Blocks.ai</title>
      <dc:creator>Kayley Smith</dc:creator>
      <pubDate>Fri, 07 Aug 2026 22:27:39 +0000</pubDate>
      <link>https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb</link>
      <guid>https://dev.to/kayleykiwi/business-idea-validator-agent-with-vercels-eve-blocksai-58mb</guid>
      <description>&lt;p&gt;My colleague created the following tutorial I just had share. It's super useful for getting actually usable answers from AI agents about your ideas(not just yes-man activities or context-less decisions). &lt;/p&gt;

&lt;p&gt;The fastest way to get a bad answer from AI is to ask it whether or not your idea is a good one. A single model can produce a persuasive argument in either direction, and even with edits to the skills files, it doesn’t expose (well) which assumptions actually determine the outcome.&lt;/p&gt;

&lt;p&gt;In this tutorial, we explore a completely different approach. We use &lt;a href="https://eve.dev/docs" rel="noopener noreferrer"&gt;eve&lt;/a&gt;, Vercel's filesystem-first framework for durable agents, to build a venture analyst that prepares a consistent evidence pack. The agent then calls &lt;a href="https://app.blocks.ai/agents/council_of_agents" rel="noopener noreferrer"&gt;@&lt;code&gt;council_of_agents&lt;/code&gt;&lt;/a&gt; on the &lt;a href="https://blocks.ai" rel="noopener noreferrer"&gt;Blocks Network&lt;/a&gt;, where specialist judges examine feasibility, risk, and value before the eve agent makes its final recommendation.&lt;/p&gt;

&lt;p&gt;The result at the end of this video will be a repeatable decision process that tells a founder what is known, what is merely assumed, and which cheap experiment should come next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll build using eve and &lt;a href="http://Blocks.ai" rel="noopener noreferrer"&gt;Blocks.ai&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;By the end of this tutorial, you will have an eve agent that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collects only the missing parts of a business idea
&lt;/li&gt;
&lt;li&gt;creates a concise analysis pack covering the problem, customer, solution, monetization, competition, risks, and value hypothesis
&lt;/li&gt;
&lt;li&gt;calls the Blocks.ai &lt;code&gt;council_of_agents&lt;/code&gt; through a typed eve tool
&lt;/li&gt;
&lt;li&gt;collects the council's returned artifacts
&lt;/li&gt;
&lt;li&gt;produces a scored &lt;code&gt;pursue&lt;/code&gt;, &lt;code&gt;pivot&lt;/code&gt;, or &lt;code&gt;kill&lt;/code&gt; verdict
&lt;/li&gt;
&lt;li&gt;recommends exactly three inexpensive experiments that could change the decision
&lt;/li&gt;
&lt;li&gt;can be verified end to end through eve's durable session stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post turns the live demo into a repeatable build and explains how each part of the workflow fits together.&lt;/p&gt;

&lt;h2&gt;
  
  
  The resulting workflow
&lt;/h2&gt;

&lt;p&gt;The agent follows one controlled path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A founder describes a problem and proposed business.
&lt;/li&gt;
&lt;li&gt;The eve agent asks only for critical information that is still missing.
&lt;/li&gt;
&lt;li&gt;Its &lt;code&gt;validate_business_idea&lt;/code&gt; skill turns the conversation into an analysis pack.
&lt;/li&gt;
&lt;li&gt;The typed &lt;code&gt;call_council_of_agents&lt;/code&gt; tool sends the problem and proposed solution to Blocks.ai.
&lt;/li&gt;
&lt;li&gt;The Blocks Council evaluates feasibility, risk, and value, then returns its findings as artifacts.
&lt;/li&gt;
&lt;li&gt;The eve agent combines those findings with its own analysis.
&lt;/li&gt;
&lt;li&gt;The founder receives a verdict, scorecard, risks, and three next experiments.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The opinionated parts live in Markdown. The network boundary lives in TypeScript. That separation is one of the nicest properties of this build: changing the analysis method does not require rewriting the SDK integration, and changing the external agent does not require burying business policy in application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you begin
&lt;/h2&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 24.x, which is the major currently declared by the eve scaffold
&lt;/li&gt;
&lt;li&gt;npm, which ships with Node.js
&lt;/li&gt;
&lt;li&gt;a credential for the runtime model you choose
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.blocks.ai/manage/api-keys" rel="noopener noreferrer"&gt;a Blocks.ai account and API key&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blocks.ai/docs/cli-reference" rel="noopener noreferrer"&gt;the Blocks.ai CLI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Scaffold the eve project
&lt;/h2&gt;

&lt;p&gt;Create the project with the standard command from the &lt;a href="https://eve.dev/docs/getting-started" rel="noopener noreferrer"&gt;eve Getting Started guide&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx eve@latest init business-idea-validator
&lt;span class="nb"&gt;cd &lt;/span&gt;business-idea-validator
npm &lt;span class="nb"&gt;install&lt;/span&gt; @blocks-network/sdk@^1.0.11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scaffold installs eve, &lt;code&gt;ai&lt;/code&gt;, and Zod, creates the &lt;code&gt;agent/&lt;/code&gt; directory, and adds the &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;, and &lt;code&gt;start&lt;/code&gt; scripts. If the initializer starts the development interface, stop it with Ctrl+C before continuing.&lt;/p&gt;

&lt;p&gt;Create the additional directories used by this agent:&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="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; agent/lib agent/tools agent/skills/validate_business_idea
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the next steps, the authored part of the project will look 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;business-idea-validator/
└── agent/
    ├── agent.ts
    ├── instructions.md
    ├── lib/
    │   └── blocks.ts
    ├── skills/
    │   └── validate_business_idea/
    │       └── SKILL.md
    └── tools/
        └── call_council_of_agents.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Configure the eve runtime
&lt;/h2&gt;

&lt;p&gt;Replace &lt;code&gt;agent/agent.ts&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anthropic/claude-sonnet-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the runtime model used by the finished agent. Grok 4.5 appears in the video as the model inside Cursor that authors the project; it is not the model serving user requests.&lt;/p&gt;

&lt;p&gt;Sonnet 5 is not required for the pattern. You can replace the model ID with another &lt;a href="https://eve.dev/docs/agent-config" rel="noopener noreferrer"&gt;eve-compatible model&lt;/a&gt; for which you have credentials. The rest of the agent and its Council integration stay the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Give the agent a strict decision policy
&lt;/h2&gt;

&lt;p&gt;Replace &lt;code&gt;agent/instructions.md&lt;/code&gt; with the complete always-on policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Identity

You are a tough but constructive venture analyst. You validate business ideas
with clear evidence, labeled assumptions, and actionable next steps. You do not
cheerlead weak ideas, and you do not dismiss strong ones without reason.

# Standing rules

1. Clarify the idea before judging. Ask only for missing critical fields:
   problem, ICP (ideal customer), solution, monetization, and stage. Do not dump
   a long form.
2. Produce evidence-based analysis. Label assumptions explicitly. Prefer
   specific risks and disconfirming tests over vague advice.
3. When validating a business idea, load the `validate_business_idea` skill and
   follow it.
4. Always call the `call_council_of_agents` tool before giving a final
   recommendation. Never invent a council verdict.
5. Return a structured scorecard covering: market, problem urgency,
   differentiation, go-to-market, risks, experiments, and a final verdict
   (`pursue` / `pivot` / `kill`).
6. Include an explicit **Council findings** section that quotes or faithfully
   summarizes the Blocks council result.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The critical rule is number four: external review is &lt;strong&gt;mandatory&lt;/strong&gt; rather than an optional enhancement the runtime model may skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Put the analysis method in an eve skill
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;agent/skills/validate_business_idea/SKILL.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
description: "Use when the user wants to validate, stress-test, score, or get a go/no-go on a business idea."
---

# Validate a business idea

Follow this procedure whenever the user asks you to validate a business idea.

## 1. Intake

Collect only what is missing from:

- **Problem** — who hurts, how often, how badly
- **ICP** — ideal customer profile
- **Solution** — what you would sell or build
- **Monetization** — how money is made
- **Stage** — idea, prototype, early revenue, or scaling

If enough of these are already in the conversation, do not re-ask.

## 2. Draft an analysis pack

Write a concise internal pack for you and for the council covering:

1. Problem and solution fit
2. Market and competition (named assumptions are acceptable)
3. Differentiation
4. Go-to-market sketch
5. Risks: feasibility, demand, distribution, and unit economics
6. Value hypothesis — why this could win

## 3. Call the council

Call `call_council_of_agents` with two fields:

- `problem` — the customer pain or decision being evaluated
- `proposedSolution` — the analysis pack, including the solution, ICP,
  monetization, competition, risks, and value hypothesis

Keep each field under approximately 8,000 characters. The council runs
specialist feasibility, risk, and value review.

Do not produce a final verdict until the tool returns.

## 4. Final scorecard

Merge your analysis with the council output into this structure:

### Verdict

One of: **pursue** / **pivot** / **kill**, with one sentence explaining why.

### Scorecard

| Dimension | Score (1–5) | Notes |
| --- | --- | --- |
| Market | | |
| Problem urgency | | |
| Differentiation | | |
| Go-to-market | | |
| Overall risk | | |

### Top risks

List 3–5 concrete risks, each with a disconfirming test.

### Next experiments

Give exactly three cheap experiments that would most change the decision.

### Council findings

Faithfully summarize, or briefly quote, what `council_of_agents` returned. Call
out agreement and disagreement with your own analysis.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;eve discovers packaged skills from their directory and exposes the description as a routing hint. The model loads the full procedure only when the user's request matches it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Add the Blocks Network client
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;agent/lib/blocks.ts&lt;/code&gt;. This helper owns authentication, task submission, artifact collection, timeout handling, billing-mode fallback, and cleanup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;BillingModeMismatchError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;TaskClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;decodeInlineArtifact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;textPart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@blocks-network/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;COUNCIL_AGENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;council_of_agents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_TIMEOUT_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PART_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_FIELD_CHARS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CouncilCallResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;agentName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;terminalState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;billingMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;partId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;artifactCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;requireApiKey&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOCKS_API_KEY&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLOCKS_API_KEY is missing. Run `blocks login --write-env` from the project directory.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trimmed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trimmed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;MAX_FIELD_CHARS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;trimmed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;trimmed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MAX_FIELD_CHARS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;\n…[truncated &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;collectArtifactText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Awaited&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskClient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;artifactCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listArtifacts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;refs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;decodeInlineArtifact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downloadArtifact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// A binary or unavailable artifact should not hide readable findings.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;artifactCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;refs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitWithMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;billingMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CouncilCallResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TaskClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;billingMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Awaited&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskClient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;agentName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;COUNCIL_AGENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;requestParts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;textPart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PART_ID&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;terminal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForTerminal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;artifactCount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;collectArtifactText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;agentName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;COUNCIL_AGENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;terminalState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;terminal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;billingMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;partId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PART_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="s2"&gt;`(Council task &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;terminal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with no text artifacts. Task id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;artifactCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callCouncilOfAgents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;proposedSolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CouncilCallResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;requireApiKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeoutMs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;timeoutMs&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_TIMEOUT_MS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;problem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;proposed_solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;proposedSolution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proposed_solution&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;submitWithMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;BillingModeMismatchError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;submitWithMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request part ID is &lt;code&gt;request&lt;/code&gt;, matching the Council agent's input contract. The client must also use the same billing mode as the registered agent, so the helper retries only the SDK's typed mismatch error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Expose the Council as a typed eve tool
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;agent/tools/call_council_of_agents.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineTool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eve/tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;callCouncilOfAgents&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../lib/blocks.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submit a problem and proposed solution to Blocks Network council_of_agents for multi-judge review (feasibility, risk, value). Always call before a final go/no-go recommendation.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The problem or decision to evaluate (business idea context, customer pain, constraints).&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;proposedSolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The proposed solution, including ICP, monetization, differentiation, and key assumptions.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;outputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;agentName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;terminalState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;billingMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;partId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;artifactCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proposedSolution&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;callCouncilOfAgents&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proposedSolution&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;toModelOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;`Council (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agentName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) finished: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;terminalState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;`Task: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The filename gives the tool its model-facing name. Zod validates both sides of the application boundary, while &lt;code&gt;toModelOutput&lt;/code&gt; keeps the model context focused on the terminal state, task ID, and findings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Add credentials and compile the project
&lt;/h2&gt;

&lt;p&gt;Install the Blocks CLI if it is not already available, authenticate, and let it write &lt;code&gt;BLOCKS_API_KEY&lt;/code&gt; into the project environment file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @blocks-network/cli
blocks login &lt;span class="nt"&gt;--write-env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the Vercel AI Gateway credential to the same &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI_GATEWAY_API_KEY=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;blocks login --write-env&lt;/code&gt; supplies &lt;code&gt;BLOCKS_API_KEY&lt;/code&gt;; do not replace or remove that entry when adding the gateway key. Keep both values out of prompts, screenshots, source files, and version control.&lt;/p&gt;

&lt;p&gt;Add an explicit type-check script, then compile the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm pkg &lt;span class="nb"&gt;set &lt;/span&gt;scripts.typecheck&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;
npm run typecheck
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, compilation must pass before you spend time or credits on a live model or Council call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Run the agent locally
&lt;/h2&gt;

&lt;p&gt;Start eve's development interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s try it. Here, we start with a simple idea: selling lemonade from an existing stand on a parcel beside a crowded street, charging $2 per cup.&lt;/p&gt;

&lt;p&gt;Try a prompt with enough context for the agent to begin, but leave a few genuine unknowns:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Validate my lemonade stand idea. I own a parcel beside a street that I believe has a lot of foot traffic, and I already have a stand. I want to sell lemonade for $2 per cup. Tell me whether I should pursue it and what I need to test first.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If working correctly, the agent should clarify important missing information, prepare its analysis pack, call the council, and wait for the real result before responding.&lt;/p&gt;

&lt;p&gt;In the recorded run, the final verdict was &lt;strong&gt;pivot&lt;/strong&gt;: run a small, structured pilot before treating the idea as a real business. The agent recognized the low cost of testing and the advantage of owning the land and stand, but it also surfaced the assumptions that had not been validated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether the street actually has useful pedestrian traffic
&lt;/li&gt;
&lt;li&gt;whether selling there is permitted
&lt;/li&gt;
&lt;li&gt;whether the founder's time is worth the likely return
&lt;/li&gt;
&lt;li&gt;what the stand can earn under real conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a good example of what &lt;code&gt;pivot&lt;/code&gt; means in this system. It’s not an acceptance or a rejection, it’s a request to turn a cheap assumption into evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What moved across the network
&lt;/h2&gt;

&lt;p&gt;The workflow keeps a useful boundary between local execution and remote review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The credentials are stored in the local environment.&lt;/strong&gt; The runtime uses them for provider and Blocks.ai authentication, but never intentionally places them in the council task payload.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The eve agent sends a bounded analysis payload.&lt;/strong&gt; It contains the problem and proposed solution, not the entire local workspace or raw conversation history.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocks.ai carries the task to @&lt;code&gt;council_of_agents&lt;/code&gt;.&lt;/strong&gt; The council's findings return as task artifacts.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The final decision remains with the eve agent.&lt;/strong&gt; It must report the council faithfully, but it merges those findings with its own scorecard, risks, and experiments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The council is an advisory layer, not an oracle. Multiple model judgments can broaden a review, but they do not turn assumptions into customer evidence. The final output should always tell the founder what to test in the real world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this pattern is useful beyond startup ideas
&lt;/h2&gt;

&lt;p&gt;The same architecture works whenever one agent should prepare context and another should provide a specialized second opinion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;architecture reviews before implementation
&lt;/li&gt;
&lt;li&gt;security or compliance checks before deployment
&lt;/li&gt;
&lt;li&gt;pricing and positioning reviews before a launch
&lt;/li&gt;
&lt;li&gt;incident-response plans before execution
&lt;/li&gt;
&lt;li&gt;research synthesis reviewed by multiple domain specialists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reusable pattern is simple: keep orchestration and durable conversation in eve, encode the process as a skill, put external access behind typed tools, and use Blocks.ai to reach the specialist agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting common challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The eve interface starts, but the first model turn fails
&lt;/h3&gt;

&lt;p&gt;Check &lt;code&gt;AI_GATEWAY_API_KEY&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt; and confirm it has access to the runtime model. Restart the dev process after changing environment variables.&lt;/p&gt;

&lt;p&gt;The first &lt;code&gt;npm run build&lt;/code&gt; may also need network access while eve downloads the AI Gateway model catalog. If you deliberately use a custom or unlisted model, set &lt;code&gt;modelContextWindowTokens&lt;/code&gt; in &lt;code&gt;agent/agent.ts&lt;/code&gt; rather than guessing silently.&lt;/p&gt;

&lt;h3&gt;
  
  
  The council tool says &lt;code&gt;BLOCKS_API_KEY&lt;/code&gt; is missing
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;blocks login --write-env&lt;/code&gt; from your project directory or add a valid key to &lt;code&gt;.env&lt;/code&gt;, then restart eve. Do not paste the key into the agent conversation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Blocks task rejects the billing mode
&lt;/h3&gt;

&lt;p&gt;The integration already retries a typed &lt;code&gt;BillingModeMismatchError&lt;/code&gt; from &lt;code&gt;free&lt;/code&gt; to &lt;code&gt;paid&lt;/code&gt;. If the second call also fails, confirm that your account may call the target agent and that its current listing and billing configuration permit the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  The council completes without readable findings
&lt;/h3&gt;

&lt;p&gt;Use the returned task ID to inspect the task in Blocks.ai. The integration reports a no-artifact result explicitly rather than allowing the eve agent to invent council feedback.&lt;/p&gt;

&lt;p&gt;Council runs can take several minutes, and an individual judge may time out while the overall task still returns useful findings. Treat warnings in the returned artifact as part of the evidence, not as text to hide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to take it next
&lt;/h2&gt;

&lt;p&gt;The demo proves the core loop, but a production version should add domain-specific evidence sources, evaluation cases, telemetry, and explicit approval policies for any tool that can create an external side effect. Eve may replay a tool execution interrupted mid-step, so paid or otherwise side-effecting council calls also need an application-level idempotency or deduplication strategy. You could also store historical experiments and bring their measured results into the next council review.&lt;/p&gt;

&lt;p&gt;For now, the most important outcome is already here: instead of asking one model for confidence, the founder gets a structured disagreement, a visible evidence gap, and a cheap next move.&lt;/p&gt;

&lt;p&gt;Try the agent first, then explore the &lt;a href="https://eve.dev/docs" rel="noopener noreferrer"&gt;eve documentation&lt;/a&gt;, read the &lt;a href="https://blocks.ai/docs" rel="noopener noreferrer"&gt;Blocks.ai docs&lt;/a&gt;, and replace the lemonade stand with an idea you care about. &lt;/p&gt;

&lt;p&gt;Tell us what you think – give me your thoughts and feedback over on X at &lt;a href="https://x.com/getbold_" rel="noopener noreferrer"&gt;@getbold_&lt;/a&gt;.&lt;br&gt;&lt;br&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzourwkgvfsuz4rbcipc2.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzourwkgvfsuz4rbcipc2.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
