<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anton Parmuzin</title>
    <description>The latest articles on DEV Community by Anton Parmuzin (@para1992).</description>
    <link>https://dev.to/para1992</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4079047%2Fd67c4d40-a1c8-44ba-9d6b-5c3aa856a7c5.png</url>
      <title>DEV Community: Anton Parmuzin</title>
      <link>https://dev.to/para1992</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/para1992"/>
    <language>en</language>
    <item>
      <title>I built a Laravel package for LLM workflows with hard token and cost limits</title>
      <dc:creator>Anton Parmuzin</dc:creator>
      <pubDate>Sat, 15 Aug 2026 13:50:08 +0000</pubDate>
      <link>https://dev.to/para1992/i-built-a-laravel-package-for-llm-workflows-with-hard-token-and-cost-limits-1gb5</link>
      <guid>https://dev.to/para1992/i-built-a-laravel-package-for-llm-workflows-with-hard-token-and-cost-limits-1gb5</guid>
      <description>&lt;p&gt;I'm building Laravel Rick, a durable workflow runtime around Laravel AI. The model call itself is the easy part. The hard part starts when workflows run through queues, survive worker crashes, wait for humans, enforce budgets, and must not repeat paid provider work after retry.&lt;/p&gt;

&lt;p&gt;Update — v0.4.1: Rick now has class-based workflows, ordinary PHP steps, native Laravel AI agent steps, WorkflowState, progress tracking, human input gates, and recovery without re-paying for successful provider work.&lt;/p&gt;

&lt;p&gt;The core flow is simple: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;BRIEF → DRAFT → EDIT → QUALITY CHECK → OUTPUT&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rick handles the infrastructure around the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hard token and cost budgets&lt;/li&gt;
&lt;li&gt;provider-attempt accounting&lt;/li&gt;
&lt;li&gt;persisted and encrypted workflow state&lt;/li&gt;
&lt;li&gt;immutable recovery lineage&lt;/li&gt;
&lt;li&gt;reuse of successful paid invocations&lt;/li&gt;
&lt;li&gt;tenant isolation&lt;/li&gt;
&lt;li&gt;human input gates&lt;/li&gt;
&lt;li&gt;progress and metrics&lt;/li&gt;
&lt;li&gt;transactional outbox delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, say you need to generate an article:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleWorkflow&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Workflow&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'article'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;WorkflowBuilder&lt;/span&gt; &lt;span class="nv"&gt;$workflow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;WorkflowBuilder&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$workflow&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCostUsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'0.02'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LoadBrief&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'load-brief'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DraftArticle&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'draft'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EditArticle&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'article'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'article'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ArticleWorkflow&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'brief'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$brief&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is what happens when something fails. A queue retry does not silently authorize another paid provider request. If successful provider work can be safely reused during recovery, Rick reuses it instead of paying for it again.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;a href="https://github.com/para1992/laravel-rick" rel="noopener noreferrer"&gt;Laravel Rick&lt;/a&gt;&lt;/strong&gt; is open source.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm especially interested in feedback from Laravel developers already running AI workloads through queues, human review, or multi-step business processes. The same approach works for support&lt;br&gt;
workflows, data processing, structured generation, or any other multi-step LLM task.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>laravel</category>
      <category>showdev</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
