<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Life Savor Engineering Blog</title>
  <subtitle>Technical insights, architecture decisions, and engineering updates from the Life Savor team.</subtitle>
  <link href="https://blog.env.lifesavor.ai/feed.xml" rel="self"/>
  <link href="https://blog.env.lifesavor.ai/"/>
  <updated>2025-05-16T00:00:00.000Z</updated>
  <id>https://blog.env.lifesavor.ai/</id>
  <author>
    <name>Life Savor Engineering</name>
  </author>
  
  <entry>
    <title>Welcome to the Life Savor Engineering Blog</title>
    <link href="https://blog.env.lifesavor.ai/hello-world/"/>
    <updated>2025-05-16T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/hello-world/</id>
    <content type="html">&lt;p&gt;We&#39;re launching this blog to share what we&#39;re building, how it works, and what we&#39;ve learned along the way.&lt;/p&gt;
&lt;p&gt;Life Savor is a local-first AI platform. Your agent runs on your device — your data stays with you. We believe AI should be private, fast, and extensible. This blog is where we&#39;ll unpack the technical decisions behind that vision.&lt;/p&gt;
&lt;h2 id=&quot;what-to-expect&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/hello-world/#what-to-expect&quot;&gt;What to Expect&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;ll be writing about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How the agent runtime works under the hood&lt;/li&gt;
&lt;li&gt;Building skills, assistants, and model components&lt;/li&gt;
&lt;li&gt;The developer SDK and marketplace ecosystem&lt;/li&gt;
&lt;li&gt;Infrastructure, deployment, and platform engineering&lt;/li&gt;
&lt;li&gt;Lessons learned shipping cross-platform software&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whether you&#39;re a developer building on the platform or just curious about how local AI agents work, we hope you&#39;ll find something useful here.&lt;/p&gt;
&lt;p&gt;First up: a look at how the Life Savor runtime actually executes your AI workloads.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>How the Life Savor Runtime Works</title>
    <link href="https://blog.env.lifesavor.ai/how-the-runtime-works/"/>
    <updated>2025-05-14T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/how-the-runtime-works/</id>
    <content type="html">&lt;p&gt;The Life Savor agent is a single binary that runs on your machine. It connects to the platform, manages AI models, executes skills, and keeps everything private by default. Here&#39;s how it all fits together.&lt;/p&gt;
&lt;h2 id=&quot;zero-built-in-models&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#zero-built-in-models&quot;&gt;Zero Built-In Models&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The agent ships with no model providers baked in. Every model — whether it&#39;s GPT-4o via API or a local LLaMA running on your GPU — is delivered as an installable component from the marketplace.&lt;/p&gt;
&lt;p&gt;This means the base agent is small and fast to install. You add only the capabilities you need.&lt;/p&gt;
&lt;h2 id=&quot;the-component-architecture&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#the-component-architecture&quot;&gt;The Component Architecture&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you install a model component, it registers with the agent&#39;s &lt;strong&gt;Integration Registry&lt;/strong&gt;. The registry tracks each provider&#39;s lifecycle: registration, health status, capabilities, and routing.&lt;/p&gt;
&lt;p&gt;When you send a message to your agent, the &lt;strong&gt;Inference Bridge&lt;/strong&gt; routes your request to the right model provider based on what&#39;s installed and healthy. If you have a local model loaded, it goes there. If you&#39;re using a cloud API, it routes through the gateway.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;You → Agent → Inference Bridge → Registered Model Provider → Response
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;three-ways-to-run-a-model&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#three-ways-to-run-a-model&quot;&gt;Three Ways to Run a Model&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Model components follow one of three patterns:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;How it works&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routes through the Life Savor API for centralized billing&lt;/td&gt;
&lt;td&gt;GPT-4o, Claude, Gemini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs on your hardware via PyTorch or ONNX Runtime&lt;/td&gt;
&lt;td&gt;LLaMA 3, Mistral 7B, Phi-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BYOK&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses your own API key, calls the vendor directly&lt;/td&gt;
&lt;td&gt;GPT-4o-BYOK, Claude-BYOK&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;local-model-execution&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#local-model-execution&quot;&gt;Local Model Execution&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For local models, the agent includes a dual-runtime engine supporting both PyTorch and ONNX Runtime. It automatically detects your hardware — CUDA on NVIDIA GPUs, Metal Performance Shaders on Apple Silicon, DirectML on Windows — and picks the fastest path.&lt;/p&gt;
&lt;p&gt;Models move through three states:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hot&lt;/strong&gt; — loaded in memory, ready for instant inference&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warm&lt;/strong&gt; — partially loaded, fast to activate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cold&lt;/strong&gt; — on disk, needs to be loaded before use&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The agent manages these transitions automatically based on usage patterns and available memory.&lt;/p&gt;
&lt;h2 id=&quot;skill-execution&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#skill-execution&quot;&gt;Skill Execution&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Skills are sandboxed extensions that give your agent new capabilities — think of them as tools. A skill might fetch your calendar, summarize a document, or query a database.&lt;/p&gt;
&lt;p&gt;When the agent invokes a skill, it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Spawns the skill as a child process&lt;/li&gt;
&lt;li&gt;Sends a JSON request to the skill&#39;s stdin&lt;/li&gt;
&lt;li&gt;Reads the JSON response from stdout&lt;/li&gt;
&lt;li&gt;Enforces a timeout (30 seconds by default)&lt;/li&gt;
&lt;li&gt;Caps output at 1MB to prevent runaway processes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The skill runs in a restricted environment — no inherited environment variables, limited filesystem access, bounded output. If it misbehaves, the agent terminates it cleanly (SIGTERM first, then SIGKILL after a grace period).&lt;/p&gt;
&lt;p&gt;Skills can be written in any language. The agent doesn&#39;t care if it&#39;s Rust, Node.js, or Python — it only cares about the JSON protocol over stdin/stdout.&lt;/p&gt;
&lt;h2 id=&quot;assistants%3A-orchestration-on-top&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#assistants%3A-orchestration-on-top&quot;&gt;Assistants: Orchestration on Top&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Assistants sit above skills and models. They combine a system prompt, tool bindings, safety guardrails, and workflow logic into a coherent persona.&lt;/p&gt;
&lt;p&gt;An assistant might:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a summarization skill to condense a long email&lt;/li&gt;
&lt;li&gt;Call a calendar skill to check your availability&lt;/li&gt;
&lt;li&gt;Route through a local model for privacy-sensitive queries&lt;/li&gt;
&lt;li&gt;Hand off to a human if it can&#39;t resolve something&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Assistants use a finite state machine internally, so they can handle multi-step workflows, wait for user confirmation, recover from errors, and track progress — all without you writing orchestration code.&lt;/p&gt;
&lt;h2 id=&quot;security-by-default&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#security-by-default&quot;&gt;Security by Default&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every model file is verified with SHA-256 checksums before loading. The manifest records the expected hash at publish time, and the agent checks it at install, startup, and upgrade. If a file has been tampered with, it&#39;s rejected immediately.&lt;/p&gt;
&lt;p&gt;Skills run in a sandbox with no access to your environment variables, secrets, or filesystem beyond what&#39;s explicitly declared. Secrets are stored in an encrypted vault on disk, never passed to child processes.&lt;/p&gt;
&lt;h2 id=&quot;what&#39;s-next&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/how-the-runtime-works/#what&#39;s-next&quot;&gt;What&#39;s Next&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the next post, we&#39;ll walk through building your first skill — a simple tool that your agent can invoke, written in about 30 lines of code.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Build Your First Skill in 30 Lines</title>
    <link href="https://blog.env.lifesavor.ai/build-your-first-skill/"/>
    <updated>2025-05-12T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/build-your-first-skill/</id>
    <content type="html">&lt;p&gt;A skill is the simplest way to extend your Life Savor agent. It&#39;s a program that reads a JSON request from stdin, does something useful, and writes a JSON response to stdout. That&#39;s it.&lt;/p&gt;
&lt;p&gt;Let&#39;s build one.&lt;/p&gt;
&lt;h2 id=&quot;what-we&#39;re-building&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#what-we&#39;re-building&quot;&gt;What We&#39;re Building&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &amp;quot;word count&amp;quot; skill. You give it text, it tells you how many words are in it. Simple, but it demonstrates the full skill lifecycle — manifest, implementation, and installation.&lt;/p&gt;
&lt;h2 id=&quot;the-manifest&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#the-manifest&quot;&gt;The Manifest&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every skill needs a &lt;code&gt;skill.json&lt;/code&gt; that tells the agent what it is and how to run it:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;skill_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;word-count&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Word Count&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Counts the number of words in a given text input&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;execution_tier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;entrypoint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;skill_id&lt;/strong&gt; — unique identifier (lowercase, hyphens only)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;execution_tier&lt;/strong&gt; — resource limits (1 is the most restricted, 3 is the most permissive)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;entrypoint&lt;/strong&gt; — how the agent launches your skill. This one runs &lt;code&gt;node index.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-implementation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#the-implementation&quot;&gt;The Implementation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&#39;s the complete skill in Node.js:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; readline &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;readline&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readline&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createInterface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdin &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

rl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;line&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;operation &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;count&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;payload&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; words &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;s+&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Boolean&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ok&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;word_count&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; words&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Unknown operation: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;operation&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s 20 lines of actual logic. The agent sends a JSON object with an &lt;code&gt;operation&lt;/code&gt; and &lt;code&gt;payload&lt;/code&gt;, and your skill responds with a &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;result&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-same-thing-in-python&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#the-same-thing-in-python&quot;&gt;The Same Thing in Python&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; json
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; line &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdin&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loads&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strip&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;operation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;count&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;payload&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        words &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;split&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ok&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;word_count&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;words&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;failed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Unknown operation: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;operation&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dumps&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flush&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Same protocol, different language. The agent doesn&#39;t care — it just speaks JSON over stdio.&lt;/p&gt;
&lt;h2 id=&quot;install-and-test&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#install-and-test&quot;&gt;Install and Test&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Put your &lt;code&gt;skill.json&lt;/code&gt; and &lt;code&gt;index.js&lt;/code&gt; (or &lt;code&gt;skill.py&lt;/code&gt;) in a directory, then install it locally:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli component &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; ./word-count&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check that it registered:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli component list&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your agent can now invoke the &lt;code&gt;word-count&lt;/code&gt; skill whenever it needs to count words in a document.&lt;/p&gt;
&lt;h2 id=&quot;adding-configuration&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#adding-configuration&quot;&gt;Adding Configuration&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What if your skill needs an API key or user preferences? Add a &lt;code&gt;config_schema&lt;/code&gt; to your manifest:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config_schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://json-schema.org/draft/2020-12/schema&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;include_characters&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Include Character Count&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Also return the character count alongside word count&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The platform renders a setup wizard automatically from your schema — no custom UI needed. Users configure your skill through a clean, consistent interface across web, iOS, and desktop.&lt;/p&gt;
&lt;h2 id=&quot;adding-setup-steps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#adding-setup-steps&quot;&gt;Adding Setup Steps&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For skills that need credentials or multi-step configuration, define &lt;code&gt;setup_steps&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;setup_steps&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Configure how the word counter behaves&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;include_characters&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each step groups related fields into a focused screen. You can add a &lt;code&gt;validation_command&lt;/code&gt; to any step if you need server-side validation (like testing an API key before proceeding).&lt;/p&gt;
&lt;h2 id=&quot;what-happens-at-runtime&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#what-happens-at-runtime&quot;&gt;What Happens at Runtime&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the agent invokes your skill:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It spawns your process in a sandbox (cleared environment, restricted paths)&lt;/li&gt;
&lt;li&gt;Writes the JSON request to your stdin&lt;/li&gt;
&lt;li&gt;Waits up to 30 seconds for a response on stdout&lt;/li&gt;
&lt;li&gt;Caps output at 1MB&lt;/li&gt;
&lt;li&gt;Terminates the process if it exceeds limits&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your skill doesn&#39;t need to manage connections, authentication, or lifecycle — the agent handles all of that.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/build-your-first-skill/#next-steps&quot;&gt;Next Steps&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This was the simplest possible skill. From here you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add multiple operations (your skill can handle many different tools)&lt;/li&gt;
&lt;li&gt;Use the MCP protocol instead of raw JSON for richer tool definitions&lt;/li&gt;
&lt;li&gt;Access system components (like the knowledge store) via the bridge&lt;/li&gt;
&lt;li&gt;Publish to the marketplace for other users to install&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the next post, we&#39;ll look at the full SDK and how to build more complex components.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The Life Savor Developer SDK: What You Can Build</title>
    <link href="https://blog.env.lifesavor.ai/intro-to-the-sdk/"/>
    <updated>2025-05-10T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/intro-to-the-sdk/</id>
    <content type="html">&lt;p&gt;The Life Savor platform is built on a component architecture. Everything — from the AI models to the tools your agent uses — is a pluggable component that you can build, publish, and share. Here&#39;s what the SDK gives you.&lt;/p&gt;
&lt;h2 id=&quot;four-component-types&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#four-component-types&quot;&gt;Four Component Types&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Skill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A tool your agent can invoke (fetch data, transform text, call APIs)&lt;/td&gt;
&lt;td&gt;Any — Rust, Node.js, Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Assistant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An orchestration layer that combines skills with prompts and guardrails&lt;/td&gt;
&lt;td&gt;Rust, Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An AI model provider (local inference or API gateway)&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A privileged platform service (voice, TTS, storage, caching)&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Most developers will start with skills. They&#39;re the simplest to build, work in any language, and cover the most common use cases.&lt;/p&gt;
&lt;h2 id=&quot;the-cli&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#the-cli&quot;&gt;The CLI&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Everything starts with &lt;code&gt;lsai-cli&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Install (macOS)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fsSL&lt;/span&gt; https://download.lifesavor.ai/lsai-cli/latest/homebrew/install.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# First-time setup&lt;/span&gt;
lsai-cli setup

&lt;span class=&quot;token comment&quot;&gt;# Create a component&lt;/span&gt;
lsai-cli components create &lt;span class=&quot;token parameter variable&quot;&gt;--name&lt;/span&gt; my-skill &lt;span class=&quot;token parameter variable&quot;&gt;--type&lt;/span&gt; skill &lt;span class=&quot;token parameter variable&quot;&gt;--language&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Set metadata&lt;/span&gt;
lsai-cli components update &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--description&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Does something useful&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--category&lt;/span&gt; Productivity &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--tags&lt;/span&gt; automation,utility

&lt;span class=&quot;token comment&quot;&gt;# Connect your GitHub repo&lt;/span&gt;
lsai-cli components connect &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; --repo-url https://github.com/you/my-skill

&lt;span class=&quot;token comment&quot;&gt;# Submit for review&lt;/span&gt;
lsai-cli components submit &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Build for all platforms&lt;/span&gt;
lsai-cli builds submit &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; --all-platforms

&lt;span class=&quot;token comment&quot;&gt;# Publish (after QA approval)&lt;/span&gt;
lsai-cli components publish &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;.0 &lt;span class=&quot;token parameter variable&quot;&gt;--notes&lt;/span&gt; CHANGELOG.md&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The full lifecycle: &lt;strong&gt;create → metadata → connect repo → submit → build → QA → publish&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;skills%3A-any-language%2C-one-protocol&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#skills%3A-any-language%2C-one-protocol&quot;&gt;Skills: Any Language, One Protocol&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Skills communicate over JSON stdin/stdout. The agent spawns your skill as a child process, sends a request, and reads the response. You can write skills in whatever language you&#39;re comfortable with.&lt;/p&gt;
&lt;p&gt;The manifest (&lt;code&gt;skill.json&lt;/code&gt;) declares your skill&#39;s identity, entrypoint, configuration schema, and setup steps. The platform renders the configuration UI automatically — you never build a settings page.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;skill_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;my-skill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;My Skill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A useful skill for Life Savor agents&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;execution_tier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;entrypoint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;python&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;python&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;skill.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Skills run sandboxed: cleared environment, restricted filesystem, bounded output, enforced timeouts.&lt;/p&gt;
&lt;h2 id=&quot;assistants%3A-orchestration-without-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#assistants%3A-orchestration-without-code&quot;&gt;Assistants: Orchestration Without Code&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Assistants combine multiple skills into a coherent workflow. You define:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System prompt&lt;/strong&gt; — with `` template substitution&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool bindings&lt;/strong&gt; — map logical names to concrete skill IDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guardrails&lt;/strong&gt; — safety rules evaluated before/after LLM calls (block, warn, or log)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handoff rules&lt;/strong&gt; — when to transfer to another assistant or a human&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context strategy&lt;/strong&gt; — how to manage the conversation window (sliding, summarize, truncate)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; definition &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AssistantDefinitionBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;support-assistant&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;display_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Support Assistant&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;system_prompt_template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;You help users with  questions.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;variable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;domain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;account management&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assistants run in two modes: &lt;strong&gt;Interactive&lt;/strong&gt; (conversational, with user confirmation steps) or &lt;strong&gt;Programmatic&lt;/strong&gt; (execute to completion without interaction).&lt;/p&gt;
&lt;h2 id=&quot;models%3A-four-provider-patterns&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#models%3A-four-provider-patterns&quot;&gt;Models: Four Provider Patterns&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you&#39;re building a model component, you implement the &lt;code&gt;LlmProvider&lt;/code&gt; trait in Rust:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Gateway&lt;/strong&gt; — route through the Life Savor API (centralized billing, no user API keys needed)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local&lt;/strong&gt; — run on the user&#39;s hardware via PyTorch or ONNX Runtime&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BYOK&lt;/strong&gt; — user supplies their own vendor API key, calls the API directly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The agent handles model state management (hot/warm/cold), hardware detection, health monitoring, and routing — your component just implements inference.&lt;/p&gt;
&lt;p&gt;Voice and text-to-speech aren&#39;t model components — they&#39;re system components that provide an input/output channel to the agent. Think of voice as a way to &lt;em&gt;get to&lt;/em&gt; a model, not a model itself.&lt;/p&gt;
&lt;h2 id=&quot;the-javascript-sdk&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#the-javascript-sdk&quot;&gt;The JavaScript SDK&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For skills that need configuration, the JS SDK (&lt;code&gt;skill-config-sdk.js&lt;/code&gt;) provides helpers for defining schemas and handling validation:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createConfigSchema&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; createSetupStep&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handleValidation &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./skill-config-sdk&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; schema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createConfigSchema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;api_key&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;string&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;API Key&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Your service API key&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&#39;x-secret&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;api_key&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fields marked &lt;code&gt;x-secret&lt;/code&gt; are stored in the agent&#39;s encrypted vault and masked in the UI. The platform handles all the crypto — you just declare which fields are sensitive.&lt;/p&gt;
&lt;h2 id=&quot;the-marketplace&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#the-marketplace&quot;&gt;The Marketplace&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once your component passes QA review, it&#39;s published to the marketplace. Users can discover and install it from the web, mobile app, or CLI:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli component &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; my-skill&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Components are code-signed, checksum-verified, and sandboxed at runtime. The platform handles distribution, updates, and compatibility checking.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/intro-to-the-sdk/#getting-started&quot;&gt;Getting Started&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Install the CLI: &lt;code&gt;curl -fsSL https://download.lifesavor.ai/lsai-cli/latest/homebrew/install.sh | bash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a developer account at &lt;a href=&quot;https://developer.lifesavor.ai/&quot;&gt;developer.lifesavor.ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;lsai-cli setup&lt;/code&gt; with your API key&lt;/li&gt;
&lt;li&gt;Create your first component: &lt;code&gt;lsai-cli components create --name my-skill --type skill --language node&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.dev.lifesavor.ai/&quot;&gt;developer documentation&lt;/a&gt; has full API references, examples, and guides for each component type.&lt;/p&gt;
&lt;p&gt;We&#39;re excited to see what you build.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Become a Life Savor Developer: Build Components, Earn Revenue</title>
    <link href="https://blog.env.lifesavor.ai/become-a-developer/"/>
    <updated>2025-05-08T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/become-a-developer/</id>
    <content type="html">&lt;p&gt;The Life Savor marketplace isn&#39;t just a place to find tools — it&#39;s a platform where developers earn real money by building components that other users install. Whether you build a simple skill, a fine-tuned model, or a full assistant workflow, you set the price and keep the majority of the revenue.&lt;/p&gt;
&lt;p&gt;Here&#39;s how it works and what you can build.&lt;/p&gt;
&lt;h2 id=&quot;the-opportunity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#the-opportunity&quot;&gt;The Opportunity&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every Life Savor agent is extensible. Users install components to add capabilities — a skill that connects to their CRM, a model fine-tuned for medical terminology, an assistant that handles customer support workflows. The marketplace is where supply meets demand.&lt;/p&gt;
&lt;p&gt;As a developer, you publish components and choose your pricing model:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pricing Model&lt;/th&gt;
&lt;th&gt;How it works&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No charge, maximizes installs&lt;/td&gt;
&lt;td&gt;Building reputation, open-source tools, lead generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;One-time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;User pays once to install&lt;/td&gt;
&lt;td&gt;Utilities, simple skills, standalone tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Subscription&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recurring monthly revenue&lt;/td&gt;
&lt;td&gt;Premium assistants, maintained integrations, model access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You set the price. The platform handles billing, distribution, updates, and compatibility.&lt;/p&gt;
&lt;h2 id=&quot;what-you-can-build&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#what-you-can-build&quot;&gt;What You Can Build&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;skills-%E2%80%94-the-fastest-path-to-revenue&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#skills-%E2%80%94-the-fastest-path-to-revenue&quot;&gt;Skills — The Fastest Path to Revenue&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Skills are the simplest component type and the easiest to monetize. A skill is a tool your agent can invoke — it could be anything from a weather lookup to a complex data pipeline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why skills sell:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Users need integrations with specific services (Slack, Jira, Salesforce, HubSpot)&lt;/li&gt;
&lt;li&gt;Niche tools that solve real problems command premium prices&lt;/li&gt;
&lt;li&gt;Low maintenance once built — the sandbox handles security and isolation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Revenue potential:&lt;/strong&gt; A well-built skill in a popular category (Productivity, Communication, Developer Tools) with subscription pricing can generate steady recurring revenue from a growing user base.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Categories in demand:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Productivity — task management, scheduling, workflow automation&lt;/li&gt;
&lt;li&gt;Communication — messaging integrations, email tools, notification routing&lt;/li&gt;
&lt;li&gt;Developer Tools — code analysis, CI/CD helpers, testing utilities&lt;/li&gt;
&lt;li&gt;Data — retrieval, transformation, API connectors&lt;/li&gt;
&lt;li&gt;Security — scanning, compliance checking, credential management&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;models-%E2%80%94-high-value%2C-technical-depth&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#models-%E2%80%94-high-value%2C-technical-depth&quot;&gt;Models — High Value, Technical Depth&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Model components provide AI inference capabilities. This is where the highest-value opportunities live, especially for developers with ML expertise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What you can build:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fine-tuned models&lt;/strong&gt; — take an open-source base model and fine-tune it for a specific domain (legal, medical, financial, code generation for a specific framework)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quantized models&lt;/strong&gt; — optimize existing models for edge devices (4-bit, 8-bit quantization for laptops and phones)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specialized models&lt;/strong&gt; — NER, classification, sentiment analysis, or other task-specific models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API wrappers&lt;/strong&gt; — connect new model providers to the platform (emerging LLM APIs, specialized inference services)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Why models command premium pricing:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fine-tuning requires expertise and compute that most users don&#39;t have&lt;/li&gt;
&lt;li&gt;Domain-specific models deliver measurably better results than general-purpose ones&lt;/li&gt;
&lt;li&gt;Users will pay for models that run locally on their hardware (privacy, speed, no API costs)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Revenue potential:&lt;/strong&gt; A fine-tuned model for a specific industry (e.g., a legal document analyzer or a medical coding assistant) can justify subscription pricing because it delivers ongoing value that improves with updates.&lt;/p&gt;
&lt;h3 id=&quot;assistants-%E2%80%94-workflow-automation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#assistants-%E2%80%94-workflow-automation&quot;&gt;Assistants — Workflow Automation&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Assistants combine skills, models, and orchestration logic into complete workflows. They&#39;re the most complex component type but also the most valuable to end users.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What you can build:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A customer support assistant that triages tickets, looks up account info, and drafts responses&lt;/li&gt;
&lt;li&gt;A research assistant that searches multiple sources, summarizes findings, and formats reports&lt;/li&gt;
&lt;li&gt;A coding assistant tuned for a specific framework or language with custom guardrails&lt;/li&gt;
&lt;li&gt;A personal finance assistant that categorizes transactions and generates insights&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Why assistants sell:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They solve complete problems, not just individual tasks&lt;/li&gt;
&lt;li&gt;Users pay for the orchestration logic — the &amp;quot;how things work together&amp;quot; part&lt;/li&gt;
&lt;li&gt;Guardrails and handoff rules make them safe for business use&lt;/li&gt;
&lt;li&gt;They can be customized per-user through configuration schemas&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Revenue potential:&lt;/strong&gt; Assistants that automate real business workflows (support, sales, operations) justify the highest subscription prices because they replace hours of manual work.&lt;/p&gt;
&lt;h3 id=&quot;fine-tuning-services&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#fine-tuning-services&quot;&gt;Fine-Tuning Services&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you have ML expertise, you can build and sell fine-tuned model components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with an open-source base model (LLaMA, Mistral, Phi, Qwen)&lt;/li&gt;
&lt;li&gt;Fine-tune with LoRA/QLoRA on domain-specific data&lt;/li&gt;
&lt;li&gt;Package as a model component with the proper manifest&lt;/li&gt;
&lt;li&gt;Publish with subscription pricing for ongoing updates&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The platform supports LoRA adapter loading, so you can ship lightweight adapters that users apply on top of base models they already have installed. This means smaller downloads and faster iteration.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#getting-started&quot;&gt;Getting Started&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1.-create-your-developer-account&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#1.-create-your-developer-account&quot;&gt;1. Create Your Developer Account&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sign up at &lt;a href=&quot;https://developer.lifesavor.ai/&quot;&gt;developer.lifesavor.ai&lt;/a&gt;. You&#39;ll get access to the developer portal, API keys, and the component management dashboard.&lt;/p&gt;
&lt;h3 id=&quot;2.-install-the-cli&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#2.-install-the-cli&quot;&gt;2. Install the CLI&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fsSL&lt;/span&gt; https://download.lifesavor.ai/lsai-cli/latest/homebrew/install.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;
lsai-cli setup&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3.-build-your-first-component&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#3.-build-your-first-component&quot;&gt;3. Build Your First Component&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Start with a skill — it&#39;s the fastest path from idea to published component:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components create &lt;span class=&quot;token parameter variable&quot;&gt;--name&lt;/span&gt; my-skill &lt;span class=&quot;token parameter variable&quot;&gt;--type&lt;/span&gt; skill &lt;span class=&quot;token parameter variable&quot;&gt;--language&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4.-set-your-pricing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#4.-set-your-pricing&quot;&gt;4. Set Your Pricing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Choose free, one-time, or subscription. You can always change this later, but starting with a free tier to build installs and reviews is a common strategy.&lt;/p&gt;
&lt;h3 id=&quot;5.-submit-and-publish&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#5.-submit-and-publish&quot;&gt;5. Submit and Publish&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components submit &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
lsai-cli builds submit &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; --all-platforms
&lt;span class=&quot;token comment&quot;&gt;# After QA approval:&lt;/span&gt;
lsai-cli components publish &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;.0 &lt;span class=&quot;token parameter variable&quot;&gt;--notes&lt;/span&gt; CHANGELOG.md&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;tips-for-success&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#tips-for-success&quot;&gt;Tips for Success&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Start small.&lt;/strong&gt; Your first component doesn&#39;t need to be complex. A well-built skill that solves one problem cleanly will outperform a bloated one that tries to do everything.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pick a niche.&lt;/strong&gt; The marketplace rewards specificity. &amp;quot;Salesforce Lead Scorer&amp;quot; will outsell &amp;quot;Generic CRM Tool&amp;quot; because users search for solutions to specific problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Maintain your components.&lt;/strong&gt; Subscription pricing works when users trust that you&#39;ll keep things updated. Regular updates, responsive support, and clear changelogs build that trust.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use the configuration system.&lt;/strong&gt; Skills with proper &lt;code&gt;config_schema&lt;/code&gt; and &lt;code&gt;setup_steps&lt;/code&gt; get higher ratings because they&#39;re easier to set up. The platform renders the UI for you — just declare your fields.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Write documentation.&lt;/strong&gt; Components with a &lt;code&gt;usage_guide&lt;/code&gt; and examples in their manifest get more installs. The agent&#39;s LLM can read your docs to help users get started.&lt;/p&gt;
&lt;h2 id=&quot;the-developer-community&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/become-a-developer/#the-developer-community&quot;&gt;The Developer Community&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;re building a platform where independent developers can earn meaningful revenue by solving real problems. The marketplace is young — early developers who establish themselves in key categories will have a significant advantage as the user base grows.&lt;/p&gt;
&lt;p&gt;Join us at &lt;a href=&quot;https://developer.lifesavor.ai/&quot;&gt;developer.lifesavor.ai&lt;/a&gt; and start building.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Privacy First: How the PII Interceptor Protects Your Data</title>
    <link href="https://blog.env.lifesavor.ai/privacy-first/"/>
    <updated>2025-05-06T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/privacy-first/</id>
    <content type="html">&lt;p&gt;Every message that flows through your Life Savor agent — whether it&#39;s going to an AI model, a skill, another agent, or a system event — passes through the PII Interceptor first. It&#39;s not optional. It&#39;s not configurable by components. It&#39;s a fixed part of the pipeline that protects your personal information before anything else touches it.&lt;/p&gt;
&lt;p&gt;Here&#39;s how it works and why we built it this way.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#the-problem&quot;&gt;The Problem&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you talk to an AI agent, you inevitably share personal information. Your name, email, phone number, address, dates of birth — it all comes up naturally in conversation. If that data gets sent to a cloud model, stored in a skill&#39;s database, or relayed to another agent, you&#39;ve lost control of it.&lt;/p&gt;
&lt;p&gt;Most platforms treat privacy as an afterthought — a settings toggle or a terms-of-service checkbox. We treat it as architecture.&lt;/p&gt;
&lt;h2 id=&quot;how-the-interceptor-works&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#how-the-interceptor-works&quot;&gt;How the Interceptor Works&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The interceptor sits in a fixed position in the message pipeline. Components cannot bypass it, reorder it, or disable it. Every message goes through two detection layers:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 1: Pattern Matching&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A regex scanner catches structured PII with known formats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Credit card numbers&lt;/li&gt;
&lt;li&gt;Social Security numbers&lt;/li&gt;
&lt;li&gt;Email addresses&lt;/li&gt;
&lt;li&gt;Phone numbers&lt;/li&gt;
&lt;li&gt;Dates of birth&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is fast and deterministic — no AI model needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: AI-Powered Detection&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A Named Entity Recognition (NER) model runs locally on your device to catch PII that doesn&#39;t follow a fixed pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Names (given names, surnames)&lt;/li&gt;
&lt;li&gt;Addresses (cities, streets, building numbers)&lt;/li&gt;
&lt;li&gt;Identity documents (driver&#39;s license numbers, passport numbers)&lt;/li&gt;
&lt;li&gt;Temporal information (dates, times that could identify you)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The NER model supports multiple languages and runs entirely on your hardware. Your text never leaves your device for PII detection.&lt;/p&gt;
&lt;h2 id=&quot;what-happens-when-pii-is-found&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#what-happens-when-pii-is-found&quot;&gt;What Happens When PII Is Found&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the interceptor detects personal information, it doesn&#39;t just delete it. It replaces it with a &lt;strong&gt;vault tag&lt;/strong&gt; — a structured token that preserves the semantic meaning without exposing the actual data:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;My email is john@example.com&amp;quot; 
    → &amp;quot;My email is &amp;lt;&amp;lt;PII:EMAIL:agent1,user1,org1,a3f2c1&amp;gt;&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The vault tag tells the AI model &amp;quot;there&#39;s an email address here&amp;quot; without revealing what it is. The model can still reason about the message (&amp;quot;the user shared their email&amp;quot;) without ever seeing the actual address.&lt;/p&gt;
&lt;p&gt;The original value is stored in your local encrypted vault, tied to your identity. Only you can retrieve it.&lt;/p&gt;
&lt;h2 id=&quot;security-levels&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#security-levels&quot;&gt;Security Levels&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Not all PII is equally sensitive. A first name is less sensitive than a Social Security number. The interceptor classifies detected PII into security levels:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Open&lt;/td&gt;
&lt;td&gt;No PII detected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Personal&lt;/td&gt;
&lt;td&gt;Names, cities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Private&lt;/td&gt;
&lt;td&gt;Email addresses, phone numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Protected&lt;/td&gt;
&lt;td&gt;Dates of birth, ages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Guarded&lt;/td&gt;
&lt;td&gt;Driver&#39;s license numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;SSNs, passport numbers, credit cards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Compound&lt;/td&gt;
&lt;td&gt;Multiple high-sensitivity items together&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These levels control who can de-tokenize (retrieve the original value). Low-sensitivity items can be resolved automatically when you request them. High-sensitivity items require explicit confirmation. Critical items may be permanently tokenized depending on your settings.&lt;/p&gt;
&lt;h2 id=&quot;exfiltration-detection&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#exfiltration-detection&quot;&gt;Exfiltration Detection&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The interceptor doesn&#39;t just look at individual messages — it watches patterns across conversations. If a skill or model starts accumulating multiple types of PII from you (your name in one message, your address in another, your phone number in a third), the interceptor flags it as a potential exfiltration attempt and blocks further data flow.&lt;/p&gt;
&lt;p&gt;This catches sophisticated attacks where individually harmless requests combine to build a profile of you.&lt;/p&gt;
&lt;h2 id=&quot;every-channel%2C-every-direction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#every-channel%2C-every-direction&quot;&gt;Every Channel, Every Direction&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The interceptor covers all communication paths:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LLM inference&lt;/strong&gt; — before your message reaches any model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skill I/O&lt;/strong&gt; — before data is sent to any skill process&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent-to-agent&lt;/strong&gt; — before messages relay between agents&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System events&lt;/strong&gt; — before internal events are logged or transmitted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And it works in both directions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inbound&lt;/strong&gt;: PII is tokenized before reaching the model, then content safety is checked&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outbound&lt;/strong&gt;: Content safety is checked first, then PII verification ensures no new personal data was introduced&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;per-component-configuration&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#per-component-configuration&quot;&gt;Per-Component Configuration&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can configure interception levels per provider or skill:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full&lt;/strong&gt; (default) — regex + NER scanning on everything&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Regex only&lt;/strong&gt; — fast pattern matching without the NER model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disabled&lt;/strong&gt; — for trusted system components that need raw data (like your local calendar integration)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also allowlist specific PII categories per component. If your email skill legitimately needs to see email addresses, you can grant that — but only for that specific skill.&lt;/p&gt;
&lt;h2 id=&quot;de-tokenization%3A-getting-your-data-back&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#de-tokenization%3A-getting-your-data-back&quot;&gt;De-tokenization: Getting Your Data Back&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you need the original value (for example, to actually send that email), you request de-tokenization. The system checks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Are you the owner of this data?&lt;/li&gt;
&lt;li&gt;Does the requesting component have permission?&lt;/li&gt;
&lt;li&gt;What&#39;s the de-tokenization policy for this PII category?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Every de-tokenization is logged in an audit trail. You can see exactly who accessed what, when, and why.&lt;/p&gt;
&lt;h2 id=&quot;why-this-matters&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/privacy-first/#why-this-matters&quot;&gt;Why This Matters&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most AI platforms send your data to the cloud, process it on someone else&#39;s servers, and store it in someone else&#39;s database. Even &amp;quot;private&amp;quot; modes often just mean &amp;quot;we won&#39;t use it for training&amp;quot; — your data still leaves your device.&lt;/p&gt;
&lt;p&gt;With Life Savor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PII detection runs locally on your hardware&lt;/li&gt;
&lt;li&gt;Sensitive data is replaced before it reaches any model or skill&lt;/li&gt;
&lt;li&gt;Original values are stored in your local encrypted vault&lt;/li&gt;
&lt;li&gt;De-tokenization requires your explicit permission&lt;/li&gt;
&lt;li&gt;Every access is audited&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your data stays yours. That&#39;s not a feature — it&#39;s the architecture.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The Developer MCP Server: AI-Powered Development From Your IDE</title>
    <link href="https://blog.env.lifesavor.ai/developer-mcp-server/"/>
    <updated>2025-05-04T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/developer-mcp-server/</id>
    <content type="html">&lt;p&gt;Building components for Life Savor means working with manifests, build pipelines, bridge protocols, and platform APIs. The Developer MCP Server puts all of that directly in your IDE — no context switching, no browser tabs, no copy-pasting between docs and code.&lt;/p&gt;
&lt;h2 id=&quot;what-is-it%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#what-is-it%3F&quot;&gt;What Is It?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Developer MCP Server is a hosted service that implements the Model Context Protocol. You connect to it from any MCP-compatible IDE (VS Code, Cursor, Windsurf, Claude Desktop) and get access to 40+ tools for building, debugging, and managing your components — all without leaving your editor.&lt;/p&gt;
&lt;p&gt;It&#39;s like having a platform expert sitting next to you who can scaffold projects, validate your manifests, check build status, search documentation, and explain how things work.&lt;/p&gt;
&lt;h2 id=&quot;setting-it-up&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#setting-it-up&quot;&gt;Setting It Up&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Add this to your IDE&#39;s MCP configuration:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;lifesavor-developer&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mcp.developer.lifesavor.ai/sse&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;headers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bearer lsk_your_api_key_here&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s it. Your IDE connects, authenticates with your API key, and you have access to the full toolset.&lt;/p&gt;
&lt;h2 id=&quot;what-you-can-do&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#what-you-can-do&quot;&gt;What You Can Do&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;scaffold-components-instantly&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#scaffold-components-instantly&quot;&gt;Scaffold Components Instantly&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Instead of reading docs and creating files manually:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Scaffold a new Python skill called weather-lookup&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The server generates the complete project structure — manifest, entrypoint, configuration schema, build config — ready to customize.&lt;/p&gt;
&lt;h3 id=&quot;validate-before-you-submit&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#validate-before-you-submit&quot;&gt;Validate Before You Submit&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Catch manifest errors before they hit the build pipeline:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Validate my manifest&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The server checks your TOML for syntax errors, missing fields, invalid values, and returns actionable fixes. It can even auto-fix common issues.&lt;/p&gt;
&lt;h3 id=&quot;debug-bridge-protocol-issues&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#debug-bridge-protocol-issues&quot;&gt;Debug Bridge Protocol Issues&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When your skill isn&#39;t communicating correctly with system components:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Diagnose bridge error COMPONENT_TIMEOUT&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You get a structured diagnosis: what the error means, common causes, diagnostic steps, and links to relevant documentation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Explain the bridge flow for a skill calling the summarize operation&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Step-by-step breakdown of the dispatch flow, including timeouts and possible error codes at each stage.&lt;/p&gt;
&lt;h3 id=&quot;check-build-status-without-leaving-your-editor&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#check-build-status-without-leaving-your-editor&quot;&gt;Check Build Status Without Leaving Your Editor&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Show me my recent builds&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Get the logs for my latest failed build&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No more switching to the portal to check if your build passed. The server pulls live data from the platform.&lt;/p&gt;
&lt;h3 id=&quot;search-documentation-semantically&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#search-documentation-semantically&quot;&gt;Search Documentation Semantically&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;How do I handle validation commands in a setup step?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The server uses semantic search over the full SDK documentation. It doesn&#39;t just keyword-match — it understands what you&#39;re asking and returns the most relevant sections.&lt;/p&gt;
&lt;h3 id=&quot;ai-powered-explanations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#ai-powered-explanations&quot;&gt;AI-Powered Explanations&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Explain how the bridge dispatch works&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;What&#39;s the component lifecycle?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The server uses retrieval-augmented generation (RAG) to give you accurate, documentation-grounded explanations. It pulls relevant docs, then generates a clear answer — no hallucination, no outdated information.&lt;/p&gt;
&lt;h3 id=&quot;generate-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#generate-code&quot;&gt;Generate Code&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Generate a bridge request handler for the summarize and translate operations&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Generate test stubs for my skill&#39;s validate_credentials operation&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The server produces handler skeletons and test stubs tailored to your component type and language, following platform conventions.&lt;/p&gt;
&lt;h3 id=&quot;manage-components&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#manage-components&quot;&gt;Manage Components&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Create a new skill component called data-enricher&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Update my component&#39;s description and tags&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Submit my component for review&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Connect my GitHub repo&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Full component lifecycle management without touching the CLI or portal.&lt;/p&gt;
&lt;h2 id=&quot;how-it-speeds-up-development&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#how-it-speeds-up-development&quot;&gt;How It Speeds Up Development&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Before the MCP server:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open browser → navigate to docs → search for the right page&lt;/li&gt;
&lt;li&gt;Read the docs → switch back to IDE → write code&lt;/li&gt;
&lt;li&gt;Open terminal → run CLI commands → check output&lt;/li&gt;
&lt;li&gt;Open portal → check build status → read logs&lt;/li&gt;
&lt;li&gt;Back to IDE → fix the issue → repeat&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;With the MCP server:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ask your IDE → get the answer → write code → validate → submit&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Everything happens in one place. Your AI assistant has full context about the platform, your components, your builds, and the documentation. It can answer questions, generate code, and take actions — all in the flow of your work.&lt;/p&gt;
&lt;h2 id=&quot;what&#39;s-under-the-hood&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#what&#39;s-under-the-hood&quot;&gt;What&#39;s Under the Hood&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The MCP server is a hosted Node.js service that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Authenticates via your existing API key (&lt;code&gt;lsk_&lt;/code&gt; prefix) or OAuth&lt;/li&gt;
&lt;li&gt;Delegates data operations to the Developer API (single source of truth)&lt;/li&gt;
&lt;li&gt;Uses Amazon Bedrock + Knowledge Bases for semantic search and AI features&lt;/li&gt;
&lt;li&gt;Maintains session state (active component, language preference) in Redis&lt;/li&gt;
&lt;li&gt;Scales horizontally behind an ALB with sticky sessions for SSE&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your data is isolated — you can only access your own components, builds, and logs. The server enforces ownership checks on every request.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/developer-mcp-server/#getting-started&quot;&gt;Getting Started&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Generate an API key at &lt;a href=&quot;https://developer.lifesavor.ai/api-keys&quot;&gt;developer.lifesavor.ai/api-keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add the MCP server config to your IDE&lt;/li&gt;
&lt;li&gt;Start asking questions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The server works with any MCP-compatible client. If your IDE supports MCP, it supports the Life Savor Developer Server.&lt;/p&gt;
&lt;p&gt;Try it: ask it to scaffold your first component, then validate the manifest, then explain how to add a configuration schema. The whole flow happens in your editor.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Preparing Your Developer Environment: Account, CLI, GitHub App, and First Build</title>
    <link href="https://blog.env.lifesavor.ai/prepare-your-dev-environment/"/>
    <updated>2025-05-02T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/prepare-your-dev-environment/</id>
    <content type="html">&lt;p&gt;Before you build your first component, you need a few things set up: a developer account, the CLI tool, a connected GitHub repository, and the GitHub App installed. This guide walks through the complete setup so you&#39;re ready to build, submit, and publish.&lt;/p&gt;
&lt;h2 id=&quot;step-1%3A-create-your-developer-account&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-1%3A-create-your-developer-account&quot;&gt;Step 1: Create Your Developer Account&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Head to &lt;a href=&quot;https://developer.lifesavor.ai/&quot;&gt;developer.lifesavor.ai&lt;/a&gt; and sign up. You can use Google OAuth or email — either works. Complete the developer agreement and fill in your profile.&lt;/p&gt;
&lt;p&gt;Once you&#39;re in, generate an API key from the portal (Settings → API Keys). Your key will have an &lt;code&gt;lsk_&lt;/code&gt; prefix. Save it somewhere secure — you&#39;ll need it for the CLI and the MCP server.&lt;/p&gt;
&lt;p&gt;API keys have scopes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Read&lt;/strong&gt; — view components, builds, logs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write&lt;/strong&gt; — create, update, submit, build, publish&lt;/li&gt;
&lt;li&gt;For development, generate a key with both scopes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;step-2%3A-install-the-cli&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-2%3A-install-the-cli&quot;&gt;Step 2: Install the CLI&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;lsai-cli&lt;/code&gt; is your primary tool for managing components from the terminal.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# macOS (Homebrew)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fsSL&lt;/span&gt; https://download.lifesavor.ai/lsai-cli/latest/homebrew/install.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Debian / Ubuntu&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fsSL&lt;/span&gt; https://download.lifesavor.ai/lsai-cli/apt/setup.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Fedora / RHEL / Amazon Linux&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fsSL&lt;/span&gt; https://download.lifesavor.ai/lsai-cli/yum/setup.sh &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Windows&lt;/span&gt;
winget &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; LifeSavorAI.lsai-cli

&lt;span class=&quot;token comment&quot;&gt;# From source (Rust 1.75+)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--path&lt;/span&gt; developer/cli&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then configure it with your API key:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli setup
&lt;span class=&quot;token comment&quot;&gt;# Paste your lsk_ key when prompted&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Verify it worked&lt;/span&gt;
lsai-cli &lt;span class=&quot;token function&quot;&gt;whoami&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see your display name, email, and key scopes.&lt;/p&gt;
&lt;h2 id=&quot;step-3%3A-install-the-github-app&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-3%3A-install-the-github-app&quot;&gt;Step 3: Install the GitHub App&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Life Savor GitHub App gives the build pipeline access to your repository. It replaces the old shared-token approach with scoped, per-developer access that you control.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why a GitHub App?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You grant access only to the repos you choose&lt;/li&gt;
&lt;li&gt;Permissions are scoped (read-only code access for builds)&lt;/li&gt;
&lt;li&gt;You can revoke access anytime from your GitHub settings&lt;/li&gt;
&lt;li&gt;No shared tokens or manual key exchange&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;How to install:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to your component&#39;s page in the developer portal&lt;/li&gt;
&lt;li&gt;Click &amp;quot;Connect Repository&amp;quot;&lt;/li&gt;
&lt;li&gt;You&#39;ll be redirected to GitHub to install the Life Savor app&lt;/li&gt;
&lt;li&gt;Select the repository (or repositories) you want to grant access to&lt;/li&gt;
&lt;li&gt;GitHub redirects you back — the connection completes automatically&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Or from the CLI:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components connect &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  --repo-url https://github.com/you/my-skill&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the GitHub App isn&#39;t installed yet, the CLI will print the installation URL and guide you through it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Already installed the app?&lt;/strong&gt; If you&#39;ve previously installed it for another component, the platform detects your existing installation and skips the install step — it just connects the new repo directly.&lt;/p&gt;
&lt;h2 id=&quot;step-4%3A-create-your-first-component&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-4%3A-create-your-first-component&quot;&gt;Step 4: Create Your First Component&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components create &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--name&lt;/span&gt; my-first-skill &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--type&lt;/span&gt; skill &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--language&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a draft component on the platform and returns a component ID. Write it down.&lt;/p&gt;
&lt;h2 id=&quot;step-5%3A-set-required-metadata&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-5%3A-set-required-metadata&quot;&gt;Step 5: Set Required Metadata&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you can submit for review, you need a description, category, tags, compatibility, and license:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components update &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--description&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A skill that does something useful&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--category&lt;/span&gt; Productivity &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--tags&lt;/span&gt; automation,utility &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--compatibility&lt;/span&gt; linux,macos,windows &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--license&lt;/span&gt; MIT&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Valid categories:&lt;/strong&gt; Productivity, Communication, Developer Tools, Data, Media, Security, Automation, Monitoring, General&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Valid platforms:&lt;/strong&gt; linux, macos, windows, ios, android, tvos&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Valid licenses:&lt;/strong&gt; MIT, Apache-2.0, GPL-3.0, BSD-2-Clause, BSD-3-Clause, ISC, MPL-2.0, LGPL-3.0, Proprietary, Custom&lt;/p&gt;
&lt;h2 id=&quot;step-6%3A-add-build-configuration&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-6%3A-add-build-configuration&quot;&gt;Step 6: Add Build Configuration&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Create a &lt;code&gt;lifesavor-build.yml&lt;/code&gt; in your repository root:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; skill
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;skill
&lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; node
  &lt;span class=&quot;token key atrule&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; npm run build
  &lt;span class=&quot;token key atrule&quot;&gt;artifact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dist/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Rust components:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; skill
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;skill
&lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; rust
  &lt;span class=&quot;token key atrule&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cargo build &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;release
  &lt;span class=&quot;token key atrule&quot;&gt;artifact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; target/release/my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;skill&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells the build pipeline how to compile your component and where to find the output.&lt;/p&gt;
&lt;h2 id=&quot;step-7%3A-set-build-targets&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-7%3A-set-build-targets&quot;&gt;Step 7: Set Build Targets&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Choose which platforms to build for:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli builds set-targets &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--platforms&lt;/span&gt; linux-x86_64,linux-arm64,macos-arm64,windows-x86_64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can start with just one platform and add more later.&lt;/p&gt;
&lt;h2 id=&quot;step-8%3A-submit-for-review&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-8%3A-submit-for-review&quot;&gt;Step 8: Submit for Review&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components submit &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This puts your component in the QA review queue. The platform checks that all required metadata is present. If anything&#39;s missing, you&#39;ll get a clear error message telling you what to fix.&lt;/p&gt;
&lt;h2 id=&quot;step-9%3A-trigger-a-build&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-9%3A-trigger-a-build&quot;&gt;Step 9: Trigger a Build&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Build for all configured platforms&lt;/span&gt;
lsai-cli builds submit &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; --all-platforms

&lt;span class=&quot;token comment&quot;&gt;# Or just one platform&lt;/span&gt;
lsai-cli builds submit &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--platform&lt;/span&gt; linux-x86_64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check build status:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli builds list &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
lsai-cli builds logs &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--status&lt;/span&gt; failed&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;step-10%3A-publish&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#step-10%3A-publish&quot;&gt;Step 10: Publish&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once QA approves your component and you have at least one successful build:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components publish &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;.0 &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--notes&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Initial release&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your component is now live on the marketplace.&lt;/p&gt;
&lt;h2 id=&quot;optional%3A-set-up-the-mcp-server&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#optional%3A-set-up-the-mcp-server&quot;&gt;Optional: Set Up the MCP Server&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a faster development experience, connect the Developer MCP Server to your IDE. Add this to your MCP configuration:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;lifesavor-developer&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mcp.developer.lifesavor.ai/sse&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;headers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bearer lsk_your_key_here&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can scaffold, validate, build, and manage components directly from your editor.&lt;/p&gt;
&lt;h2 id=&quot;optional%3A-set-up-webhooks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#optional%3A-set-up-webhooks&quot;&gt;Optional: Set Up Webhooks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Get notified when builds complete or reviews finish:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli webhooks create &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; https://your-server.com/webhooks/lifesavor &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--events&lt;/span&gt; build.succeeded,build.failed,review.approved&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Webhook payloads are signed with HMAC-SHA256 so you can verify they&#39;re authentic.&lt;/p&gt;
&lt;h2 id=&quot;optional%3A-build-secrets&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#optional%3A-build-secrets&quot;&gt;Optional: Build Secrets&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your build needs API keys or credentials (for integration tests, for example):&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli secrets &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--component&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--key&lt;/span&gt; MY_API_KEY &lt;span class=&quot;token parameter variable&quot;&gt;--value&lt;/span&gt; sk-abc123&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Secrets are stored encrypted and injected as environment variables during builds. They&#39;re never exposed in logs.&lt;/p&gt;
&lt;h2 id=&quot;the-complete-flow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#the-complete-flow&quot;&gt;The Complete Flow&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Account → CLI → GitHub App → Create → Metadata → Build Config → Submit → Build → Publish
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once this is set up, your ongoing workflow is just: push code → build triggers → publish new version. The infrastructure stays out of your way.&lt;/p&gt;
&lt;h2 id=&quot;troubleshooting&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/prepare-your-dev-environment/#troubleshooting&quot;&gt;Troubleshooting&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Repository access denied&amp;quot;&lt;/strong&gt; — The GitHub App isn&#39;t installed or doesn&#39;t have access to that repo. Visit the installation URL and grant access.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Missing required fields&amp;quot;&lt;/strong&gt; — Run &lt;code&gt;lsai-cli components status &amp;lt;id&amp;gt;&lt;/code&gt; to see what&#39;s missing before submission.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Build failed&amp;quot;&lt;/strong&gt; — Check logs with &lt;code&gt;lsai-cli builds logs --component &amp;lt;id&amp;gt; --status failed&lt;/code&gt;. Common issues: missing dependencies, wrong artifact path, build command errors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Key expired&amp;quot;&lt;/strong&gt; — Generate a new API key from the portal and run &lt;code&gt;lsai-cli setup&lt;/code&gt; again.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;That&#39;s everything. You&#39;re set up to build, test, and publish components on the Life Savor platform. Start with a simple skill, get comfortable with the workflow, then scale up to models and assistants.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>What Happens When You Talk to Your Agent</title>
    <link href="https://blog.env.lifesavor.ai/request-lifecycle/"/>
    <updated>2025-04-30T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/request-lifecycle/</id>
    <content type="html">&lt;p&gt;You type a message. A few seconds later, your agent responds. But what actually happens in between? Here&#39;s the full lifecycle of a request through the Life Savor agent.&lt;/p&gt;
&lt;h2 id=&quot;the-journey-of-a-message&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#the-journey-of-a-message&quot;&gt;The Journey of a Message&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;You type &amp;quot;Summarize my last 5 emails&amp;quot;
    ↓
1. PII Interceptor scans your message
2. Content Safety checks the sanitized text
3. Inference Bridge routes to your configured model
4. Model generates a plan: &amp;quot;I need to call the email skill&amp;quot;
5. Agent invokes the email skill (sandboxed)
6. Skill returns your 5 most recent emails
7. PII Interceptor scans the skill output
8. Model receives sanitized emails, generates summary
9. Content Safety checks the response
10. PII Interceptor verifies no new PII leaked
11. Response delivered to you
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;step-by-step&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#step-by-step&quot;&gt;Step by Step&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1.-interception-(inbound)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#1.-interception-(inbound)&quot;&gt;1. Interception (Inbound)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Your message hits the interceptor pipeline before anything else sees it. The regex scanner checks for structured PII (emails, phone numbers, credit cards). The NER model checks for unstructured PII (names, addresses). Anything sensitive gets replaced with vault tags.&lt;/p&gt;
&lt;p&gt;The model never sees your actual email address — it sees &lt;code&gt;&amp;lt;&amp;lt;PII:EMAIL:...&amp;gt;&amp;gt;&lt;/code&gt; and knows &amp;quot;there&#39;s an email here&amp;quot; without knowing what it is.&lt;/p&gt;
&lt;h3 id=&quot;2.-model-routing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#2.-model-routing&quot;&gt;2. Model Routing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Inference Bridge looks at what models you have installed and healthy. If you have a local LLaMA loaded (hot state), it routes there. If you&#39;re using GPT-4o via API, it goes through the gateway. The routing is automatic based on your configuration and model availability.&lt;/p&gt;
&lt;h3 id=&quot;3.-tool-use&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#3.-tool-use&quot;&gt;3. Tool Use&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The model decides it needs to call a skill. It generates a tool call request — &amp;quot;invoke the email skill with operation &lt;code&gt;list_recent&lt;/code&gt; and parameter &lt;code&gt;count: 5&lt;/code&gt;.&amp;quot;&lt;/p&gt;
&lt;p&gt;The agent validates this against the skill&#39;s permission graph. Does this model have permission to invoke this skill? Is the skill healthy? Is it within rate limits?&lt;/p&gt;
&lt;h3 id=&quot;4.-skill-execution&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#4.-skill-execution&quot;&gt;4. Skill Execution&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The agent spawns the email skill as a sandboxed child process. It sends the request via JSON stdin. The skill fetches your emails (using credentials from the encrypted vault), formats the response, and writes it to stdout.&lt;/p&gt;
&lt;p&gt;The skill&#39;s output goes through the interceptor too — any PII in the email content gets tokenized before the model sees it.&lt;/p&gt;
&lt;h3 id=&quot;5.-response-generation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#5.-response-generation&quot;&gt;5. Response Generation&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The model receives the sanitized email summaries and generates your response. This output goes through content safety (checking for harmful content) and then PII verification (ensuring the model didn&#39;t hallucinate or reconstruct personal information).&lt;/p&gt;
&lt;h3 id=&quot;6.-delivery&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#6.-delivery&quot;&gt;6. Delivery&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The clean, safe response reaches you. The whole thing took a few seconds, but your personal information never left your device unprotected, and every step was logged for your audit trail.&lt;/p&gt;
&lt;h2 id=&quot;why-this-order-matters&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/request-lifecycle/#why-this-order-matters&quot;&gt;Why This Order Matters&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The interception order is fixed and enforced at the pipeline level. Components cannot bypass it, reorder it, or disable it. This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No skill can see your raw PII unless explicitly allowlisted&lt;/li&gt;
&lt;li&gt;No model receives unscanned input&lt;/li&gt;
&lt;li&gt;No response leaves without safety verification&lt;/li&gt;
&lt;li&gt;Every step is traceable via correlation IDs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This isn&#39;t a feature you enable — it&#39;s how the system works by default.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Local vs Cloud Models: When to Use Each</title>
    <link href="https://blog.env.lifesavor.ai/local-vs-cloud/"/>
    <updated>2025-04-28T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/local-vs-cloud/</id>
    <content type="html">&lt;p&gt;Life Savor supports both local models (running on your hardware) and cloud models (via API). You&#39;re not locked into either — you can mix and match based on what you&#39;re doing. Here&#39;s how to think about the tradeoff.&lt;/p&gt;
&lt;h2 id=&quot;when-local-makes-sense&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/local-vs-cloud/#when-local-makes-sense&quot;&gt;When Local Makes Sense&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Privacy-sensitive work.&lt;/strong&gt; If you&#39;re processing medical records, legal documents, financial data, or anything you wouldn&#39;t want leaving your device — local models keep everything on your hardware. The PII interceptor adds another layer, but local inference means the data never hits a network at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Offline use.&lt;/strong&gt; On a plane, in a tunnel, or somewhere with unreliable internet — local models work regardless. No API calls, no latency spikes, no timeouts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Predictable latency.&lt;/strong&gt; Local inference has consistent response times. No cold starts, no rate limits, no queue behind other users. Once a model is in hot state, responses are immediate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cost at scale.&lt;/strong&gt; If you&#39;re making hundreds of requests per day, local inference is effectively free after the initial model download. No per-token billing.&lt;/p&gt;
&lt;h2 id=&quot;when-cloud-makes-sense&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/local-vs-cloud/#when-cloud-makes-sense&quot;&gt;When Cloud Makes Sense&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Capability.&lt;/strong&gt; The largest, most capable models (GPT-4o, Claude 3.7 Sonnet, Gemini 1.5 Pro) require more compute than most personal devices can provide. If you need frontier-level reasoning, cloud APIs deliver it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hardware constraints.&lt;/strong&gt; Running a 70B parameter model requires significant GPU memory. If you&#39;re on a laptop without a dedicated GPU, smaller local models may not match the quality you need. Cloud models have no hardware requirements on your end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Convenience.&lt;/strong&gt; Cloud models are instant — no download, no setup, no disk space. Install the component and start using it.&lt;/p&gt;
&lt;h2 id=&quot;the-hybrid-approach&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/local-vs-cloud/#the-hybrid-approach&quot;&gt;The Hybrid Approach&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most users end up with a mix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A local model for everyday tasks (quick questions, drafting, summarization)&lt;/li&gt;
&lt;li&gt;A cloud model for complex reasoning (analysis, coding, research)&lt;/li&gt;
&lt;li&gt;The agent routes automatically based on what&#39;s available and healthy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can configure routing preferences — &amp;quot;prefer local when available, fall back to cloud&amp;quot; — or let the agent decide based on the task.&lt;/p&gt;
&lt;h2 id=&quot;hardware-guidelines-for-local-models&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/local-vs-cloud/#hardware-guidelines-for-local-models&quot;&gt;Hardware Guidelines for Local Models&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model Size&lt;/th&gt;
&lt;th&gt;RAM Needed&lt;/th&gt;
&lt;th&gt;Good For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1-3B (TinyLlama, Phi-3 Mini)&lt;/td&gt;
&lt;td&gt;4-6 GB&lt;/td&gt;
&lt;td&gt;Simple tasks, edge devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7-8B (Mistral 7B, LLaMA 3 8B)&lt;/td&gt;
&lt;td&gt;8-12 GB&lt;/td&gt;
&lt;td&gt;General use, good quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13-22B (CodeStral, DeepSeek Coder)&lt;/td&gt;
&lt;td&gt;16-24 GB&lt;/td&gt;
&lt;td&gt;Specialized tasks, coding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;70B+ (LLaMA 3 70B)&lt;/td&gt;
&lt;td&gt;48+ GB&lt;/td&gt;
&lt;td&gt;Near-frontier quality, requires GPU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Quantized models (4-bit) cut memory requirements roughly in half with minimal quality loss. The marketplace has pre-quantized versions of popular models.&lt;/p&gt;
&lt;h2 id=&quot;byok%3A-a-middle-ground&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/local-vs-cloud/#byok%3A-a-middle-ground&quot;&gt;BYOK: A Middle Ground&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want cloud model quality but don&#39;t want billing through the platform, BYOK (Bring Your Own Key) components let you use your own API key directly. Your requests go straight to the vendor — no platform middleman, no markup. You just pay the vendor directly.&lt;/p&gt;
&lt;h2 id=&quot;bottom-line&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/local-vs-cloud/#bottom-line&quot;&gt;Bottom Line&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&#39;s no wrong answer. Start with what&#39;s convenient, then optimize based on your actual usage patterns. The agent makes switching easy — install a new model component, and it&#39;s available immediately.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Your Data Never Leaves Your Device (Unless You Want It To)</title>
    <link href="https://blog.env.lifesavor.ai/your-data-stays-local/"/>
    <updated>2025-04-26T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/your-data-stays-local/</id>
    <content type="html">&lt;p&gt;Most AI platforms work like this: you type something, it goes to a server, gets processed, and comes back. Your data lives on someone else&#39;s infrastructure, governed by someone else&#39;s privacy policy.&lt;/p&gt;
&lt;p&gt;Life Savor works differently.&lt;/p&gt;
&lt;h2 id=&quot;what-stays-local&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/your-data-stays-local/#what-stays-local&quot;&gt;What Stays Local&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Your conversations&lt;/strong&gt; — stored in an encrypted database on your device&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your credentials&lt;/strong&gt; — API keys, tokens, and passwords in a local encrypted vault&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your PII&lt;/strong&gt; — detected and tokenized before it reaches any model or skill&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your model inference&lt;/strong&gt; — when using local models, computation happens entirely on your hardware&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your skill data&lt;/strong&gt; — skills run in a sandbox on your device&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-goes-to-the-cloud-(only-when-you-choose)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/your-data-stays-local/#what-goes-to-the-cloud-(only-when-you-choose)&quot;&gt;What Goes to the Cloud (Only When You Choose)&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cloud model requests&lt;/strong&gt; — if you use GPT-4o, Claude, or other API models, your (PII-sanitized) message goes to that provider&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform sync&lt;/strong&gt; — agent status, installed components, and configuration sync with the platform for multi-device support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Marketplace installs&lt;/strong&gt; — downloading components requires internet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even when data does leave your device, the PII interceptor has already replaced sensitive information with vault tags. The cloud model sees &lt;code&gt;&amp;lt;&amp;lt;PII:EMAIL:...&amp;gt;&amp;gt;&lt;/code&gt; — not your actual email address.&lt;/p&gt;
&lt;h2 id=&quot;how-we-enforce-this&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/your-data-stays-local/#how-we-enforce-this&quot;&gt;How We Enforce This&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This isn&#39;t a promise in a terms-of-service document. It&#39;s enforced by architecture:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The interceptor is mandatory.&lt;/strong&gt; Every message passes through PII scanning before reaching any model or skill. Components cannot bypass it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Skills are sandboxed.&lt;/strong&gt; They run with a cleared environment — no access to your filesystem, environment variables, or network unless explicitly declared and approved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secrets never leave the vault.&lt;/strong&gt; API keys and credentials are resolved at runtime by the agent. Skills receive the service response, not the key itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Local models are truly local.&lt;/strong&gt; PyTorch and ONNX Runtime execute on your CPU/GPU. No telemetry, no phone-home, no cloud dependency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Everything is auditable.&lt;/strong&gt; Every PII detection, every de-tokenization, every skill invocation is logged locally. You can inspect exactly what happened.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;you&#39;re-in-control&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/your-data-stays-local/#you&#39;re-in-control&quot;&gt;You&#39;re in Control&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Want to disable PII scanning for a trusted skill? You can. Want to allow a specific model to see your email address? Configure it. Want to run completely offline with no cloud models? Install local models and disconnect.&lt;/p&gt;
&lt;p&gt;The defaults are private. The overrides are yours.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Anatomy of a Skill Manifest: Every Field Explained</title>
    <link href="https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/"/>
    <updated>2025-04-24T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/</id>
    <content type="html">&lt;p&gt;Every skill has a &lt;code&gt;skill.json&lt;/code&gt; manifest that tells the agent what it is, how to run it, what it needs, and how users configure it. Here&#39;s every field, explained.&lt;/p&gt;
&lt;h2 id=&quot;required-fields&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#required-fields&quot;&gt;Required Fields&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;skill_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;weather-lookup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Weather Lookup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Fetches current weather and forecasts for any location&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;execution_tier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Rules&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;skill_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lowercase alphanumeric + hyphens only&lt;/td&gt;
&lt;td&gt;Unique identifier on the marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any string&lt;/td&gt;
&lt;td&gt;Human-readable display name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Semver (e.g. &lt;code&gt;1.2.0&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Used for updates and compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minimum 10 characters&lt;/td&gt;
&lt;td&gt;Shown in marketplace search results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_tier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1, 2, or 3&lt;/td&gt;
&lt;td&gt;Controls resource limits and sandbox privileges&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;execution-tiers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#execution-tiers&quot;&gt;Execution Tiers&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tier 1&lt;/strong&gt; — most restricted. Short timeouts, minimal filesystem access. Good for simple tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tier 2&lt;/strong&gt; — moderate. Longer timeouts, more memory. Good for API integrations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tier 3&lt;/strong&gt; — least restricted. Extended timeouts, broader access. For complex processing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;entrypoint&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#entrypoint&quot;&gt;Entrypoint&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tells the agent how to launch your skill:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;entrypoint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dist/index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;env&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;NODE_ENV&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;production&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Options&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;node&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;binary&lt;/code&gt;, &lt;code&gt;wasm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Determines how the agent spawns the process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any executable&lt;/td&gt;
&lt;td&gt;For &lt;code&gt;binary&lt;/code&gt;, relative to skill directory. For &lt;code&gt;node&lt;/code&gt;/&lt;code&gt;python&lt;/code&gt;, the system command.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;args&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Array of strings&lt;/td&gt;
&lt;td&gt;Arguments passed to the command&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;env&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Key-value map&lt;/td&gt;
&lt;td&gt;Environment variables set for the process (in addition to sandbox defaults)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The agent clears the environment before launching your skill. Only &lt;code&gt;PATH&lt;/code&gt; and your declared &lt;code&gt;env&lt;/code&gt; vars are available. This prevents accidental secret leakage.&lt;/p&gt;
&lt;h2 id=&quot;configuration-schema&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#configuration-schema&quot;&gt;Configuration Schema&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Defines what settings your skill accepts from users:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config_schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://json-schema.org/draft/2020-12/schema&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API Key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Your weather service API key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;x-secret&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;units&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Temperature Units&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Celsius or Fahrenheit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;enum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;celsius&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fahrenheit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;celsius&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;cache_ttl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cache Duration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;How long to cache results (seconds)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;supported-field-types&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#supported-field-types&quot;&gt;Supported Field Types&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;UI Control&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text input (password if &lt;code&gt;x-secret&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;API keys, URLs, names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number input (decimals)&lt;/td&gt;
&lt;td&gt;Thresholds, ratios&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;integer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number input (whole numbers)&lt;/td&gt;
&lt;td&gt;Counts, timeouts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Toggle switch&lt;/td&gt;
&lt;td&gt;Feature flags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;array&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tag input / multi-select&lt;/td&gt;
&lt;td&gt;Lists of values&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;the-x-secret-flag&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#the-x-secret-flag&quot;&gt;The &lt;code&gt;x-secret&lt;/code&gt; Flag&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fields marked &lt;code&gt;&amp;quot;x-secret&amp;quot;: true&lt;/code&gt; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stored in the agent&#39;s encrypted vault (not in plaintext config)&lt;/li&gt;
&lt;li&gt;Masked in the UI (shown as &lt;code&gt;••••••••&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Never logged or exposed in error messages&lt;/li&gt;
&lt;li&gt;Resolved at runtime and passed to your skill securely&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;setup-steps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#setup-steps&quot;&gt;Setup Steps&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Groups config fields into a guided wizard:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;setup_steps&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;credentials&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API Credentials&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Connect your weather service account&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;validation_command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;validate_credentials&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Configure display and caching options&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;units&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cache_ttl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;step_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Unique identifier for the step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes (3-100 chars)&lt;/td&gt;
&lt;td&gt;Displayed as the step heading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes (10-500 chars)&lt;/td&gt;
&lt;td&gt;Help text below the heading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fields&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Config field names from &lt;code&gt;config_schema&lt;/code&gt; that belong to this step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validation_command&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Skill operation name the agent invokes to validate before advancing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;When &lt;code&gt;validation_command&lt;/code&gt; is set, the agent calls your skill with that operation and the user&#39;s field values. Your skill can test the API key, verify a connection, or check permissions — and return success or a specific error message.&lt;/p&gt;
&lt;h2 id=&quot;pass-through-config&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#pass-through-config&quot;&gt;Pass-Through Config&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the agent invokes your skill, the user&#39;s configured values are available to your process. The config is persisted locally on the agent and merged with any platform-provided overrides at install time.&lt;/p&gt;
&lt;p&gt;Here&#39;s how it flows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User fills in the setup wizard (or the platform sends config during install)&lt;/li&gt;
&lt;li&gt;Values are stored locally — secrets go to the encrypted vault, plain values to &lt;code&gt;config.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;At invocation time, the agent resolves secrets from the vault and passes the full config to your skill as part of the invocation payload&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your skill receives the config in the request context:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;operation&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;payload&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Seattle&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;resolved-from-vault&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;units&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;celsius&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;cache_ttl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You never need to manage credential storage yourself. Declare &lt;code&gt;x-secret&lt;/code&gt;, and the platform handles encryption, vault storage, and runtime resolution.&lt;/p&gt;
&lt;h2 id=&quot;capabilities&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#capabilities&quot;&gt;Capabilities&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Optional flags for special skill behaviors:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;capabilities&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rag_provider&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rag_provider&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This skill provides retrieval-augmented generation content to the knowledge store&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;dependencies&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#dependencies&quot;&gt;Dependencies&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Declare other skills your skill requires:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;skill_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;auth-helper&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;min_version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2.0.0&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent checks dependencies at install time and warns the user if required skills are missing or unhealthy.&lt;/p&gt;
&lt;h2 id=&quot;documentation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Bundle docs with your skill for both users and the agent&#39;s LLM:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;documentation&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;usage_guide&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;docs/usage.md&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;examples&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Basic Weather Query&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;docs/examples/basic.md&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Forecast Integration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;docs/examples/forecast.md&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent&#39;s LLM can read your documentation to help users get started. Good docs = better user experience = more installs.&lt;/p&gt;
&lt;h2 id=&quot;complete-example&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/anatomy-of-a-skill-manifest/#complete-example&quot;&gt;Complete Example&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;skill_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;weather-lookup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Weather Lookup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Fetches current weather and forecasts for any location worldwide&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Your Name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;license&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MIT&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;weather&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;forecast&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;execution_tier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;entrypoint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dist/index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;capabilities&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config_schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://json-schema.org/draft/2020-12/schema&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API Key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Your weather service API key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;x-secret&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;units&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Units&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Temperature units&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;enum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;celsius&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fahrenheit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;celsius&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;setup_steps&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;credentials&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API Credentials&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Enter your weather service API key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;validation_command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;validate_credentials&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose your display preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;units&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;documentation&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;usage_guide&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;docs/usage.md&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bookmark this page. You&#39;ll reference it every time you build a new skill.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Adding a Setup Wizard to Your Skill</title>
    <link href="https://blog.env.lifesavor.ai/setup-wizard/"/>
    <updated>2025-04-22T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/setup-wizard/</id>
    <content type="html">&lt;p&gt;A skill with a setup wizard gets more installs. Users see a clean, guided configuration flow instead of guessing what values to enter. The platform renders the UI automatically from your manifest — you just declare the fields and steps.&lt;/p&gt;
&lt;h2 id=&quot;the-basics&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#the-basics&quot;&gt;The Basics&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You need two things in your &lt;code&gt;skill.json&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;config_schema&lt;/code&gt; defining what fields exist&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;setup_steps&lt;/code&gt; array grouping those fields into screens&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config_schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://json-schema.org/draft/2020-12/schema&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API Key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Your service API key (find it in Settings → API)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;x-secret&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;workspace_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Workspace ID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The workspace to connect to&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;notify_on_error&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Error Notifications&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Send a notification when the skill encounters an error&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;workspace_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;setup_steps&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;credentials&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Connect Your Account&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Enter your API key and workspace ID to get started&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;workspace_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;validation_command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;validate_credentials&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;step_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Preferences&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Configure how the skill behaves&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;notify_on_error&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The platform renders step 1 first. The user fills in their API key and workspace ID, clicks Next, and the agent validates their credentials before advancing to step 2.&lt;/p&gt;
&lt;h2 id=&quot;adding-server-side-validation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#adding-server-side-validation&quot;&gt;Adding Server-Side Validation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;validation_command&lt;/code&gt; field tells the agent to invoke your skill with that operation name before advancing to the next step. This lets you verify credentials, test connections, or check permissions in real time.&lt;/p&gt;
&lt;p&gt;Here&#39;s a validation handler in Node.js:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; readline &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;readline&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readline&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createInterface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdin &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

rl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;line&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;operation &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;validate_credentials&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; api_key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; workspace_id &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;payload&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Test the credentials against the external service&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://api.example.com/workspaces/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;workspace_id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&#39;Authorization&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;api_key&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ok&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Connected successfully&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Invalid API key. Check that your key has workspace access.&#39;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token literal-property property&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Workspace not found. Double-check the workspace ID.&#39;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Connection failed: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The user sees your error message directly in the wizard. Clear, specific error messages (&amp;quot;Invalid API key&amp;quot; vs &amp;quot;Something went wrong&amp;quot;) make the difference between a 5-star review and a support ticket.&lt;/p&gt;
&lt;h2 id=&quot;field-types-in-practice&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#field-types-in-practice&quot;&gt;Field Types in Practice&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;secrets-(api-keys%2C-tokens)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#secrets-(api-keys%2C-tokens)&quot;&gt;Secrets (API keys, tokens)&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API Key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Your service API key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;x-secret&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rendered as a password field. Stored in the encrypted vault. Never shown in logs.&lt;/p&gt;
&lt;h3 id=&quot;dropdowns-(enum-values)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#dropdowns-(enum-values)&quot;&gt;Dropdowns (enum values)&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;region&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Region&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Which data center to connect to&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;enum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;us-east&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;us-west&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eu-west&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ap-southeast&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;us-east&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rendered as a dropdown select. The &lt;code&gt;default&lt;/code&gt; pre-selects a value.&lt;/p&gt;
&lt;h3 id=&quot;toggles-(booleans)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#toggles-(booleans)&quot;&gt;Toggles (booleans)&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;auto_sync&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Auto-Sync&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Automatically sync data every hour&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rendered as a toggle switch.&lt;/p&gt;
&lt;h3 id=&quot;numbers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#numbers&quot;&gt;Numbers&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;max_results&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Max Results&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Maximum number of results to return per query&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rendered as a number input.&lt;/p&gt;
&lt;h3 id=&quot;lists-(arrays)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#lists-(arrays)&quot;&gt;Lists (arrays)&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Channels&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Slack channels to monitor&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;general&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rendered as a tag input where users can add/remove values.&lt;/p&gt;
&lt;h2 id=&quot;tips-for-good-setup-wizards&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#tips-for-good-setup-wizards&quot;&gt;Tips for Good Setup Wizards&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Keep step 1 minimal.&lt;/strong&gt; Just credentials. Users want to verify the connection works before configuring preferences.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Write helpful descriptions.&lt;/strong&gt; Tell users where to find their API key. Link to the service&#39;s settings page in the description text.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use defaults generously.&lt;/strong&gt; Every field with a sensible default is one less decision for the user.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Validate early.&lt;/strong&gt; If an API key is wrong, catch it in step 1 — don&#39;t let users configure 5 more screens before discovering the connection doesn&#39;t work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group logically.&lt;/strong&gt; Credentials in one step, behavior in another, notifications in a third. Don&#39;t mix concerns.&lt;/p&gt;
&lt;h2 id=&quot;testing-your-wizard&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/setup-wizard/#testing-your-wizard&quot;&gt;Testing Your Wizard&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use the CLI to preview and test:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Preview how the wizard will render&lt;/span&gt;
lsai-cli skill config preview

&lt;span class=&quot;token comment&quot;&gt;# Validate your schema&lt;/span&gt;
lsai-cli skill config validate

&lt;span class=&quot;token comment&quot;&gt;# Test a validation command with sample values&lt;/span&gt;
lsai-cli skill config test-validation &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--step&lt;/span&gt; credentials &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--values&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&quot;api_key&quot;: &quot;sk-test&quot;, &quot;workspace_id&quot;: &quot;ws-123&quot;}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This runs your validation handler locally so you can verify error messages and success responses before publishing.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Testing Your Component Locally Before Submitting</title>
    <link href="https://blog.env.lifesavor.ai/testing-locally/"/>
    <updated>2025-04-20T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/testing-locally/</id>
    <content type="html">&lt;p&gt;Don&#39;t wait for the build pipeline to tell you something&#39;s broken. Test locally first — validate your manifest, run your skill in the sandbox, and catch issues before they cost you a build cycle.&lt;/p&gt;
&lt;h2 id=&quot;validate-your-manifest&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#validate-your-manifest&quot;&gt;Validate Your Manifest&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli skill config validate&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This checks your &lt;code&gt;skill.json&lt;/code&gt; for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Missing required fields&lt;/li&gt;
&lt;li&gt;Invalid field types&lt;/li&gt;
&lt;li&gt;Schema syntax errors&lt;/li&gt;
&lt;li&gt;Setup step references to non-existent fields&lt;/li&gt;
&lt;li&gt;Version format issues&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fix everything this reports before submitting.&lt;/p&gt;
&lt;h2 id=&quot;install-locally&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#install-locally&quot;&gt;Install Locally&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli component &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; ./my-skill&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This installs your skill into the local agent&#39;s skill directory, exactly as the marketplace would. The agent picks it up, registers it, and you can invoke it immediately.&lt;/p&gt;
&lt;p&gt;Check it registered:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli component list&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;test-your-skill-manually&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#test-your-skill-manually&quot;&gt;Test Your Skill Manually&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Send a request to your skill directly:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&quot;operation&quot;:&quot;my_operation&quot;,&quot;payload&quot;:{&quot;key&quot;:&quot;value&quot;}}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; dist/index.js&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should get a JSON response on stdout. If you get nothing, check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is your skill reading from stdin?&lt;/li&gt;
&lt;li&gt;Is it writing to stdout (not stderr)?&lt;/li&gt;
&lt;li&gt;Is the output valid JSON?&lt;/li&gt;
&lt;li&gt;Does it include a &lt;code&gt;status&lt;/code&gt; field?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;test-validation-commands&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#test-validation-commands&quot;&gt;Test Validation Commands&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your skill has setup steps with &lt;code&gt;validation_command&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli skill config test-validation &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--step&lt;/span&gt; credentials &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--values&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&quot;api_key&quot;: &quot;test-key-123&quot;}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This invokes your skill with the validation operation and shows you exactly what the user would see — success message or error.&lt;/p&gt;
&lt;h2 id=&quot;run-in-the-sandbox&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#run-in-the-sandbox&quot;&gt;Run in the Sandbox&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The SDK includes a sandbox runner that applies the same restrictions the agent uses:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; run &lt;span class=&quot;token parameter variable&quot;&gt;--bin&lt;/span&gt; sandbox-runner -- &lt;span class=&quot;token parameter variable&quot;&gt;--manifest&lt;/span&gt; path/to/manifest.toml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This spawns your skill with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cleared environment (only PATH + declared env vars)&lt;/li&gt;
&lt;li&gt;Restricted filesystem access&lt;/li&gt;
&lt;li&gt;Output size limits&lt;/li&gt;
&lt;li&gt;Timeout enforcement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your skill works outside the sandbox but fails inside it, you&#39;re probably:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reading environment variables that aren&#39;t declared&lt;/li&gt;
&lt;li&gt;Accessing filesystem paths that aren&#39;t allowed&lt;/li&gt;
&lt;li&gt;Producing output larger than 1MB&lt;/li&gt;
&lt;li&gt;Taking longer than 30 seconds&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;validate-build-config&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#validate-build-config&quot;&gt;Validate Build Config&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli config validate&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Checks your &lt;code&gt;lifesavor-build.yml&lt;/code&gt; for syntax errors, missing fields, and invalid values before you push.&lt;/p&gt;
&lt;h2 id=&quot;check-submission-readiness&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#check-submission-readiness&quot;&gt;Check Submission Readiness&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components status &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This shows you exactly what&#39;s missing before submission: description, category, tags, connected repo, etc. Fix everything in the checklist before running &lt;code&gt;submit&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;common-issues&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/testing-locally/#common-issues&quot;&gt;Common Issues&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Skill has no entrypoint defined&amp;quot;&lt;/strong&gt; — Your &lt;code&gt;skill.json&lt;/code&gt; is missing the &lt;code&gt;entrypoint&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Failed to parse skill response as JSON&amp;quot;&lt;/strong&gt; — Your skill is writing something other than JSON to stdout. Check for debug prints, logging to stdout, or missing newlines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Skill execution timed out&amp;quot;&lt;/strong&gt; — Your skill took longer than 30 seconds. Optimize or increase your execution tier.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Output exceeded 1MB limit&amp;quot;&lt;/strong&gt; — Your skill is returning too much data. Paginate, summarize, or stream.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Process exited with code 1&amp;quot;&lt;/strong&gt; — Your skill crashed. Run it manually with the same input to see the error.&lt;/p&gt;
&lt;p&gt;Test locally, fix locally, then push. Your build success rate will thank you.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>How the Marketplace Review Process Works</title>
    <link href="https://blog.env.lifesavor.ai/marketplace-review/"/>
    <updated>2025-04-18T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/marketplace-review/</id>
    <content type="html">&lt;p&gt;Every component goes through QA review before it&#39;s published. Here&#39;s what we check, common rejection reasons, and how to pass on the first try.&lt;/p&gt;
&lt;h2 id=&quot;the-review-flow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#the-review-flow&quot;&gt;The Review Flow&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Submit → Pending QA → In Review → Approved → Ready to Publish
                         ↓
                      Rejected → Back to Draft (fix and resubmit)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After you submit, your component enters the QA queue. A reviewer evaluates it against our checklist. If it passes, you can publish. If not, you get specific feedback on what to fix.&lt;/p&gt;
&lt;h2 id=&quot;what-we-check&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#what-we-check&quot;&gt;What We Check&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;metadata-completeness&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#metadata-completeness&quot;&gt;Metadata Completeness&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Description is clear and accurate (not just &amp;quot;a skill&amp;quot;)&lt;/li&gt;
&lt;li&gt;Category matches what the component actually does&lt;/li&gt;
&lt;li&gt;Tags are relevant and helpful for discovery&lt;/li&gt;
&lt;li&gt;License is specified&lt;/li&gt;
&lt;li&gt;Compatibility platforms are listed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;manifest-validity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#manifest-validity&quot;&gt;Manifest Validity&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;All required fields present and correctly typed&lt;/li&gt;
&lt;li&gt;Version follows semver&lt;/li&gt;
&lt;li&gt;Entrypoint command exists and is valid&lt;/li&gt;
&lt;li&gt;Config schema (if present) is well-formed&lt;/li&gt;
&lt;li&gt;Setup steps reference valid fields&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;security&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#security&quot;&gt;Security&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No hardcoded credentials or API keys in source&lt;/li&gt;
&lt;li&gt;Secrets use &lt;code&gt;x-secret&lt;/code&gt; flag properly&lt;/li&gt;
&lt;li&gt;No unnecessary filesystem access declarations&lt;/li&gt;
&lt;li&gt;No suspicious network calls&lt;/li&gt;
&lt;li&gt;Dependencies are from trusted sources&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;functionality&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#functionality&quot;&gt;Functionality&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The component actually does what the description says&lt;/li&gt;
&lt;li&gt;Error handling is reasonable (doesn&#39;t crash on bad input)&lt;/li&gt;
&lt;li&gt;Timeouts are appropriate for the execution tier&lt;/li&gt;
&lt;li&gt;Output is well-structured JSON&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;documentation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;README explains what the component does&lt;/li&gt;
&lt;li&gt;Setup instructions are clear&lt;/li&gt;
&lt;li&gt;If there&#39;s a &lt;code&gt;usage_guide&lt;/code&gt;, it&#39;s helpful&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;common-rejection-reasons&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#common-rejection-reasons&quot;&gt;Common Rejection Reasons&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Description too vague&amp;quot;&lt;/strong&gt; — &amp;quot;A useful skill&amp;quot; doesn&#39;t tell users anything. Be specific: &amp;quot;Fetches current weather and 5-day forecasts from OpenWeatherMap for any city worldwide.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Missing error handling&amp;quot;&lt;/strong&gt; — If your skill crashes on invalid input instead of returning a structured error response, it&#39;ll be rejected. Always return &lt;code&gt;{&amp;quot;status&amp;quot;: &amp;quot;failed&amp;quot;, &amp;quot;error&amp;quot;: &amp;quot;...&amp;quot;}&lt;/code&gt; instead of crashing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Hardcoded credentials&amp;quot;&lt;/strong&gt; — Any API key, token, or secret in your source code is an automatic rejection. Use &lt;code&gt;config_schema&lt;/code&gt; with &lt;code&gt;x-secret&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Execution tier mismatch&amp;quot;&lt;/strong&gt; — If your skill makes external API calls but uses tier 1 (most restricted), it may timeout. Match your tier to your actual resource needs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;No validation on required config&amp;quot;&lt;/strong&gt; — If your skill requires an API key but doesn&#39;t validate it during setup, users will get cryptic errors later. Add a &lt;code&gt;validation_command&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-to-pass-on-the-first-try&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#how-to-pass-on-the-first-try&quot;&gt;How to Pass on the First Try&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Run &lt;code&gt;lsai-cli skill config validate&lt;/code&gt;&lt;/strong&gt; — catches manifest issues before submission&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test in the sandbox&lt;/strong&gt; — if it works in the sandbox, it&#39;ll work in production&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write a real description&lt;/strong&gt; — 2-3 sentences explaining what it does and who it&#39;s for&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handle errors gracefully&lt;/strong&gt; — never crash, always return structured error responses&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use &lt;code&gt;x-secret&lt;/code&gt; for credentials&lt;/strong&gt; — no exceptions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Include a README&lt;/strong&gt; — even a short one helps&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test with bad input&lt;/strong&gt; — what happens when the API key is wrong? When the network is down? When input is empty?&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;after-rejection&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#after-rejection&quot;&gt;After Rejection&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Rejections include specific feedback. Fix the issues, then resubmit:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;lsai-cli components submit &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;component-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You don&#39;t need to create a new component — just fix and resubmit the same one. Your draft is preserved.&lt;/p&gt;
&lt;h2 id=&quot;timeline&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/marketplace-review/#timeline&quot;&gt;Timeline&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Reviews typically complete within 1-2 business days. Complex components (models, system components) may take longer. You&#39;ll get a notification when the review is complete.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Why We Chose Rust for a Cross-Platform Agent</title>
    <link href="https://blog.env.lifesavor.ai/why-rust/"/>
    <updated>2025-04-16T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/why-rust/</id>
    <content type="html">&lt;p&gt;The Life Savor agent runs on macOS, Windows, six Linux distributions, NetBSD, and OpenBSD — all from a single codebase. We chose Rust for this, and it wasn&#39;t because Rust is trendy. Here&#39;s the actual reasoning.&lt;/p&gt;
&lt;h2 id=&quot;the-requirements&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#the-requirements&quot;&gt;The Requirements&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We needed a language that could:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compile to a single native binary (no runtime dependencies)&lt;/li&gt;
&lt;li&gt;Run on every major desktop OS without a VM or interpreter&lt;/li&gt;
&lt;li&gt;Handle concurrent WebSocket connections, model inference, and skill execution simultaneously&lt;/li&gt;
&lt;li&gt;Manage memory safely without a garbage collector (predictable latency for real-time inference)&lt;/li&gt;
&lt;li&gt;Interface with native platform APIs (Keychain on macOS, Credential Manager on Windows, libsecret on Linux)&lt;/li&gt;
&lt;li&gt;Embed PyTorch and ONNX Runtime for local model inference&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;what-we-considered&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#what-we-considered&quot;&gt;What We Considered&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt; — great for servers, but CGo makes cross-compilation painful. Embedding PyTorch via CGo is fragile. The garbage collector introduces latency spikes during inference.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C++&lt;/strong&gt; — meets all technical requirements, but memory safety is manual. For a security-critical application handling PII, encrypted vaults, and sandboxed processes, we didn&#39;t want to bet on manual memory management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node.js / Python&lt;/strong&gt; — require a runtime. Distributing a Node.js app as a native binary means bundling the entire runtime. Performance for local inference is inadequate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Swift&lt;/strong&gt; — excellent on Apple platforms, but cross-platform support is limited. We use Swift for the macOS-native GUI, but the core agent needs to run everywhere.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt; — single binary, no runtime, memory safety enforced at compile time, excellent async ecosystem (tokio), first-class C FFI for PyTorch/ONNX, and compiles to every target we need.&lt;/p&gt;
&lt;h2 id=&quot;what-rust-gives-us&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#what-rust-gives-us&quot;&gt;What Rust Gives Us&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;zero-cost-abstractions-for-the-pipeline&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#zero-cost-abstractions-for-the-pipeline&quot;&gt;Zero-Cost Abstractions for the Pipeline&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The message interception pipeline processes every message through PII scanning, content safety, and routing. In Rust, this pipeline is a chain of zero-cost abstractions — no heap allocations in the hot path, no virtual dispatch overhead, no garbage collection pauses.&lt;/p&gt;
&lt;h3 id=&quot;fearless-concurrency&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#fearless-concurrency&quot;&gt;Fearless Concurrency&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The agent juggles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A persistent WebSocket connection (heartbeats, commands)&lt;/li&gt;
&lt;li&gt;Multiple skill processes (spawned, monitored, terminated)&lt;/li&gt;
&lt;li&gt;Model inference (potentially GPU-bound)&lt;/li&gt;
&lt;li&gt;File system watchers (skill directory changes)&lt;/li&gt;
&lt;li&gt;Encrypted vault operations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rust&#39;s ownership system prevents data races at compile time. We don&#39;t need mutexes around everything — the type system tells us when shared state is safe.&lt;/p&gt;
&lt;h3 id=&quot;cross-compilation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#cross-compilation&quot;&gt;Cross-Compilation&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We build for 8+ targets from a single CI pipeline:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x86_64-unknown-linux-gnu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aarch64-unknown-linux-gnu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x86_64-apple-darwin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aarch64-apple-darwin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x86_64-pc-windows-msvc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x86_64-unknown-netbsd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x86_64-unknown-openbsd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each produces a single static binary. No installer dependencies, no shared libraries to manage, no &amp;quot;works on my machine&amp;quot; issues.&lt;/p&gt;
&lt;h3 id=&quot;safe-ffi-for-ml-runtimes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#safe-ffi-for-ml-runtimes&quot;&gt;Safe FFI for ML Runtimes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The agent embeds PyTorch (via &lt;code&gt;tch-rs&lt;/code&gt;) and ONNX Runtime (via &lt;code&gt;ort&lt;/code&gt;). These are C/C++ libraries with complex memory management. Rust&#39;s FFI boundary gives us safe wrappers — if we misuse the C API, the compiler catches it.&lt;/p&gt;
&lt;h2 id=&quot;the-tradeoffs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#the-tradeoffs&quot;&gt;The Tradeoffs&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Compile times.&lt;/strong&gt; A full release build takes 5-8 minutes. Incremental debug builds are fast, but CI pipelines feel the cost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learning curve.&lt;/strong&gt; The borrow checker is real. New contributors take longer to become productive. But once code compiles, it tends to work correctly — fewer runtime bugs, fewer production incidents.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ecosystem maturity.&lt;/strong&gt; Some libraries are younger than their Go/Node equivalents. We&#39;ve contributed patches upstream and occasionally vendor dependencies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Binary size.&lt;/strong&gt; A release binary with PyTorch and ONNX Runtime linked is ~50MB. Acceptable for a desktop application, but larger than a Go binary would be.&lt;/p&gt;
&lt;h2 id=&quot;would-we-choose-it-again%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/why-rust/#would-we-choose-it-again%3F&quot;&gt;Would We Choose It Again?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yes. The combination of memory safety, native performance, cross-platform compilation, and safe C FFI is unique to Rust. For a security-critical application that runs on user devices, handles sensitive data, and embeds ML runtimes — there isn&#39;t a better option today.&lt;/p&gt;
&lt;p&gt;The agent has been running in production across all supported platforms with zero memory-safety-related bugs. The type system catches those at compile time, so they never reach users.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The Case for Local-First AI</title>
    <link href="https://blog.env.lifesavor.ai/case-for-local-first/"/>
    <updated>2025-04-14T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/case-for-local-first/</id>
    <content type="html">&lt;p&gt;The default assumption in AI today is that your data goes to the cloud. You type a message, it travels to a data center, gets processed on someone else&#39;s GPU, and the response comes back. This works, but it comes with costs that most people don&#39;t think about until it&#39;s too late.&lt;/p&gt;
&lt;p&gt;We think the future is local-first. Here&#39;s why.&lt;/p&gt;
&lt;h2 id=&quot;the-cloud-model&#39;s-hidden-costs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/case-for-local-first/#the-cloud-model&#39;s-hidden-costs&quot;&gt;The Cloud Model&#39;s Hidden Costs&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Privacy is a promise, not a guarantee.&lt;/strong&gt; When your data leaves your device, you&#39;re trusting the provider&#39;s security, their employees, their subprocessors, and their government&#39;s legal framework. One breach, one subpoena, one rogue employee — and your private conversations are exposed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Latency is variable.&lt;/strong&gt; Cloud inference depends on network conditions, server load, and queue depth. A request that takes 200ms today might take 2 seconds tomorrow during peak hours. Local inference is consistent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Availability is someone else&#39;s problem.&lt;/strong&gt; When OpenAI has an outage, your AI stops working. When your local model is loaded, it works regardless of what&#39;s happening on the internet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cost scales with usage.&lt;/strong&gt; Every token costs money. Heavy users pay hundreds per month. Local inference is free after the initial model download — your electricity bill is the only ongoing cost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You don&#39;t own the relationship.&lt;/strong&gt; The provider can change pricing, deprecate models, alter behavior, or shut down entirely. Your workflows break when their business decisions change.&lt;/p&gt;
&lt;h2 id=&quot;what-local-first-means&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/case-for-local-first/#what-local-first-means&quot;&gt;What Local-First Means&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Local-first doesn&#39;t mean local-only. It means:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Computation happens on your device by default.&lt;/strong&gt; Your data doesn&#39;t leave unless you explicitly choose a cloud model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The system works offline.&lt;/strong&gt; No internet? No problem. Your local models, your skills, your conversations — all available.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud is an option, not a requirement.&lt;/strong&gt; When you need frontier-level capability, you can opt into cloud models. But it&#39;s your choice, not the default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your data is yours.&lt;/strong&gt; Stored locally, encrypted, under your control. No training on your conversations, no data mining, no third-party access.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-hardware-inflection-point&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/case-for-local-first/#the-hardware-inflection-point&quot;&gt;The Hardware Inflection Point&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Three years ago, running a useful language model locally required a $10,000 GPU. Today:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A MacBook with 16GB unified memory runs a 7B model comfortably&lt;/li&gt;
&lt;li&gt;A gaming PC with an RTX 4070 runs a 13B model at interactive speeds&lt;/li&gt;
&lt;li&gt;Quantized models (4-bit) cut memory requirements in half with minimal quality loss&lt;/li&gt;
&lt;li&gt;Apple Silicon&#39;s unified memory architecture makes local inference surprisingly fast&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The hardware is here. The models are here (LLaMA, Mistral, Phi, Qwen — all open-source, all capable). What&#39;s been missing is the software layer that makes local AI as easy to use as cloud AI.&lt;/p&gt;
&lt;h2 id=&quot;the-hybrid-future&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/case-for-local-first/#the-hybrid-future&quot;&gt;The Hybrid Future&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We don&#39;t think cloud AI is going away. Frontier models will always push the boundaries of what&#39;s possible, and they&#39;ll always require more compute than a laptop can provide.&lt;/p&gt;
&lt;p&gt;But for 80% of daily AI use — drafting emails, summarizing documents, answering questions, managing tasks — a local 7B model is more than sufficient. It&#39;s faster, cheaper, more private, and more reliable than a cloud API.&lt;/p&gt;
&lt;p&gt;The right architecture supports both: local by default, cloud when you need it, with a privacy layer that protects you regardless of which path your data takes.&lt;/p&gt;
&lt;h2 id=&quot;what-this-means-for-developers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/case-for-local-first/#what-this-means-for-developers&quot;&gt;What This Means for Developers&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you&#39;re building on the Life Savor platform, this philosophy shapes everything:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Skills run locally&lt;/strong&gt; in a sandbox on the user&#39;s device&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Models can be local or cloud&lt;/strong&gt; — your component works either way&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User data is protected&lt;/strong&gt; by the interceptor regardless of where inference happens&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offline support is expected&lt;/strong&gt; — don&#39;t assume internet connectivity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Build for local-first, and your components work everywhere. Build for cloud-only, and you&#39;ve limited your audience to users who are always online and willing to send their data elsewhere.&lt;/p&gt;
&lt;h2 id=&quot;the-bet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/case-for-local-first/#the-bet&quot;&gt;The Bet&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;re betting that users will increasingly choose privacy, reliability, and control over convenience. That as local hardware gets more capable and open-source models get better, the gap between local and cloud will narrow to the point where most people don&#39;t need the cloud for everyday AI.&lt;/p&gt;
&lt;p&gt;That future is closer than most people think. And we&#39;re building the platform for it.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>MCP: What It Is and Why It Matters for AI Tooling</title>
    <link href="https://blog.env.lifesavor.ai/what-is-mcp/"/>
    <updated>2025-04-12T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/what-is-mcp/</id>
    <content type="html">&lt;p&gt;MCP — the Model Context Protocol — is an open standard for connecting AI models to external tools and data sources. If you&#39;ve used the Life Savor Developer MCP Server, you&#39;ve already used it. But what is it, and why does it matter?&lt;/p&gt;
&lt;h2 id=&quot;the-problem-mcp-solves&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#the-problem-mcp-solves&quot;&gt;The Problem MCP Solves&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every AI model needs access to external information. A coding assistant needs to read files. A customer support bot needs to query a database. A research agent needs to search the web.&lt;/p&gt;
&lt;p&gt;Before MCP, every integration was custom. Each AI platform had its own plugin format, its own API conventions, its own way of describing tools. If you built a tool for ChatGPT, you couldn&#39;t use it with Claude. If you built one for Claude, it didn&#39;t work with Gemini.&lt;/p&gt;
&lt;p&gt;MCP standardizes this. One protocol, one format, works everywhere.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#how-it-works&quot;&gt;How It Works&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;MCP defines three things:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tools&lt;/strong&gt; — actions the AI can take. &amp;quot;Search the database,&amp;quot; &amp;quot;create a file,&amp;quot; &amp;quot;send an email.&amp;quot; Each tool has a name, description, and input schema (what parameters it accepts).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt; — data the AI can read. Documentation pages, configuration files, database records. Read-only access to information.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prompts&lt;/strong&gt; — reusable prompt templates for common workflows. &amp;quot;Explain this error,&amp;quot; &amp;quot;review this code,&amp;quot; &amp;quot;summarize this document.&amp;quot;&lt;/p&gt;
&lt;p&gt;The AI model connects to an MCP server, discovers what tools/resources/prompts are available, and uses them as needed during a conversation.&lt;/p&gt;
&lt;h2 id=&quot;the-wire-format&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#the-wire-format&quot;&gt;The Wire Format&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;MCP uses JSON-RPC over standard transports (stdio, SSE, HTTP). A tool call looks like:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tools/call&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;params&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;search_docs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;arguments&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;query&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;how to validate a manifest&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The server responds with the result:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;To validate a manifest, use lsai-cli skill config validate...&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Simple, structured, language-agnostic.&lt;/p&gt;
&lt;h2 id=&quot;why-it-matters&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#why-it-matters&quot;&gt;Why It Matters&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt; Build a tool once, use it with any MCP-compatible AI. Your Life Savor skill can also be exposed as an MCP tool. Your MCP server works with Claude Desktop, VS Code, Cursor, Windsurf, and any future client that supports the protocol.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For users:&lt;/strong&gt; More tools available, better integrations, less vendor lock-in. When tools are standardized, the ecosystem grows faster.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For the ecosystem:&lt;/strong&gt; A shared protocol means shared tooling. Debugging tools, testing frameworks, and documentation all benefit from standardization.&lt;/p&gt;
&lt;h2 id=&quot;mcp-in-life-savor&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#mcp-in-life-savor&quot;&gt;MCP in Life Savor&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We use MCP in two ways:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. The Developer MCP Server&lt;/strong&gt; — a hosted service that gives developers IDE-integrated access to platform tools (scaffolding, validation, build management, documentation search). Connect from any MCP client and manage your components without leaving your editor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Skills can use MCP transport&lt;/strong&gt; — instead of raw JSON stdin/stdout, skills can implement the MCP protocol for richer tool definitions and capability discovery. The agent performs a capability handshake and invokes tools via MCP&#39;s JSON-RPC format.&lt;/p&gt;
&lt;h2 id=&quot;getting-started-with-mcp&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#getting-started-with-mcp&quot;&gt;Getting Started with MCP&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to build an MCP server (for any purpose, not just Life Savor):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pick a transport (stdio for local tools, SSE/HTTP for hosted services)&lt;/li&gt;
&lt;li&gt;Define your tools with names, descriptions, and JSON Schema inputs&lt;/li&gt;
&lt;li&gt;Implement the &lt;code&gt;tools/call&lt;/code&gt; handler&lt;/li&gt;
&lt;li&gt;Connect from any MCP client&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The protocol is open and well-documented. You don&#39;t need permission or a platform account to build an MCP server — it&#39;s a standard anyone can implement.&lt;/p&gt;
&lt;h2 id=&quot;the-bigger-picture&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/what-is-mcp/#the-bigger-picture&quot;&gt;The Bigger Picture&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;MCP is doing for AI tools what REST did for web APIs — creating a shared language that lets different systems work together. We&#39;re early in this standardization, but the direction is clear: AI tooling is converging on open protocols rather than proprietary plugin formats.&lt;/p&gt;
&lt;p&gt;We&#39;re building on that foundation because we believe open standards create better ecosystems than walled gardens.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Pass-Through Config: How User Settings Reach Your Skill at Runtime</title>
    <link href="https://blog.env.lifesavor.ai/pass-through-config/"/>
    <updated>2025-04-10T00:00:00.000Z</updated>
    <id>https://blog.env.lifesavor.ai/pass-through-config/</id>
    <content type="html">&lt;p&gt;When a user configures your skill through the setup wizard, those values need to reach your code at runtime. This is pass-through config — the mechanism that takes user-provided settings, stores them securely, and delivers them to your skill every time it&#39;s invoked.&lt;/p&gt;
&lt;h2 id=&quot;the-flow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#the-flow&quot;&gt;The Flow&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;User fills setup wizard
    ↓
Platform validates values (via your validation_command)
    ↓
Secrets → encrypted vault | Plain values → config.json
    ↓
User invokes your skill
    ↓
Agent resolves secrets from vault + merges config
    ↓
Your skill receives the full config in the request payload
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-your-skill-receives&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#what-your-skill-receives&quot;&gt;What Your Skill Receives&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every invocation includes the user&#39;s config alongside the operation and payload:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;operation&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fetch_data&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;payload&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;query&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;latest reports&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sk-live-abc123def456&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;workspace_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ws-789&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;max_results&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;notify_on_error&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that &lt;code&gt;api_key&lt;/code&gt; is the actual resolved value — not a vault reference. The agent handles decryption and resolution before your skill ever sees it. Your code just reads &lt;code&gt;request.config.api_key&lt;/code&gt; and uses it.&lt;/p&gt;
&lt;h2 id=&quot;how-secrets-are-handled&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#how-secrets-are-handled&quot;&gt;How Secrets Are Handled&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Fields marked with &lt;code&gt;&amp;quot;x-secret&amp;quot;: true&lt;/code&gt; in your &lt;code&gt;config_schema&lt;/code&gt; get special treatment:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; The value is encrypted with AES-256-GCM and stored in the local vault — never in plaintext on disk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI:&lt;/strong&gt; Shown as &lt;code&gt;••••••••&lt;/code&gt; after initial entry. Users can update but never view the stored value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging:&lt;/strong&gt; Never appears in logs, error messages, or debug output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resolution:&lt;/strong&gt; At invocation time, the agent decrypts the value and passes it to your skill in the &lt;code&gt;config&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sandbox:&lt;/strong&gt; The secret is in the JSON payload on stdin — it&#39;s never set as an environment variable (which could leak via &lt;code&gt;/proc&lt;/code&gt; on Linux).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your skill doesn&#39;t need to know about the vault, encryption, or key management. You declare &lt;code&gt;x-secret&lt;/code&gt;, and the platform handles the rest.&lt;/p&gt;
&lt;h2 id=&quot;config-override-at-install-time&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#config-override-at-install-time&quot;&gt;Config Override at Install Time&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a skill is installed from the marketplace, the platform can provide config overrides — default values or organization-wide settings that merge with the user&#39;s choices:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;config_override&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;api_key_source&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vault&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;default_region&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;us-east-1&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These overrides merge into the skill&#39;s &lt;code&gt;config.json&lt;/code&gt; at install time. User-provided values (from the setup wizard) take precedence over overrides.&lt;/p&gt;
&lt;h2 id=&quot;updating-config-after-install&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#updating-config-after-install&quot;&gt;Updating Config After Install&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Users can reconfigure your skill at any time through the platform UI. When they do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The setup wizard re-renders with current values (secrets shown as masked)&lt;/li&gt;
&lt;li&gt;User changes what they want&lt;/li&gt;
&lt;li&gt;Validation commands run again (if defined)&lt;/li&gt;
&lt;li&gt;New values are persisted&lt;/li&gt;
&lt;li&gt;Next invocation uses the updated config&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your skill doesn&#39;t need to handle config reloading — it gets the current config on every invocation. Stateless by design.&lt;/p&gt;
&lt;h2 id=&quot;accessing-config-in-your-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#accessing-config-in-your-code&quot;&gt;Accessing Config in Your Code&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;node.js&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#node.js&quot;&gt;Node.js&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; readline &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;readline&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; readline&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createInterface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdin &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

rl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;line&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; operation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; payload&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; config &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Use config values directly&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apiKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;api_key&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maxResults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;max_results &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Your logic here...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;python&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#python&quot;&gt;Python&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; json
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; line &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdin&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loads&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;line&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strip&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;config&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    api_key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    max_results &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;max_results&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Your logic here...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;rust&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#rust&quot;&gt;Rust&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token attribute attr-name&quot;&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;SkillRequest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    operation&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    payload&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;serde_json&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    config&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SkillConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token attribute attr-name&quot;&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;SkillConfig&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    api_key&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    max_results&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;best-practices&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#best-practices&quot;&gt;Best Practices&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Don&#39;t cache config across invocations.&lt;/strong&gt; Your skill is a short-lived process — read config from the request every time. This ensures you always have the latest values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Validate config in your validation_command, not at runtime.&lt;/strong&gt; By the time your skill is invoked, config should already be valid. The setup wizard catches errors early.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use defaults in your schema.&lt;/strong&gt; If a field has a sensible default, declare it. Users who don&#39;t customize still get working behavior.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don&#39;t log secrets.&lt;/strong&gt; Even though the agent redacts them from its own logs, your skill&#39;s stderr output might be captured. Never print config values that could be sensitive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Handle missing optional fields gracefully.&lt;/strong&gt; Not every field will be present — use defaults in your code for anything not in &lt;code&gt;required&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-security-model&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blog.env.lifesavor.ai/pass-through-config/#the-security-model&quot;&gt;The Security Model&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The pass-through config system is designed so that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Secrets are encrypted at rest (vault)&lt;/li&gt;
&lt;li&gt;Secrets are decrypted only at invocation time (just-in-time resolution)&lt;/li&gt;
&lt;li&gt;Secrets are passed via stdin (not environment variables)&lt;/li&gt;
&lt;li&gt;The skill process is sandboxed (can&#39;t read other skills&#39; configs)&lt;/li&gt;
&lt;li&gt;Config is scoped per-user, per-skill (no cross-contamination)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You get the convenience of &amp;quot;just read the config object&amp;quot; with the security of encrypted vault storage. No key management code in your skill, no credential files to protect, no rotation logic to implement.&lt;/p&gt;
</content>
  </entry>
  
</feed>
