<?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: Amara Graham</title>
    <description>The latest articles on DEV Community by Amara Graham (@missamarakay).</description>
    <link>https://dev.to/missamarakay</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1330%2Fe4706a09-0796-4d76-a451-832c6897bda5.jpg</url>
      <title>DEV Community: Amara Graham</title>
      <link>https://dev.to/missamarakay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/missamarakay"/>
    <language>en</language>
    <item>
      <title>Building a Self-Triaging CVE Checker with Gemini, Kestra, and Notion</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Fri, 03 Apr 2026 18:46:20 +0000</pubDate>
      <link>https://dev.to/missamarakay/building-a-self-triaging-cve-checker-with-gemini-kestra-and-notion-4dek</link>
      <guid>https://dev.to/missamarakay/building-a-self-triaging-cve-checker-with-gemini-kestra-and-notion-4dek</guid>
      <description>&lt;p&gt;I built a CVE checker for a nice enterprise-y use case, and of course, it's getting bigger and bigger as I go "ooooh, what if I add this?!" So this is me taking a break and telling you what I've done so far because this was the original stopping point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;I needed some kind of data to populate a Notion database (basically a table) so I could do something interesting with our &lt;a href="https://go.kestra.io/bEUrbf" rel="noopener noreferrer"&gt;Notion + Kestra plugins&lt;/a&gt;. Bonus points if I could sprinkle in some AI augmentation. Extra bonus points if I could make it a realistic enterprise example. Something that really resonates with the enterprise crowd.&lt;/p&gt;

&lt;p&gt;And immediately I was like - CVEs! &lt;/p&gt;

&lt;h3&gt;
  
  
  The distraction
&lt;/h3&gt;

&lt;p&gt;Side note, I spent far too long last week discovering that things may look like and act like Notion Pages, but a Notion Database is not a Notion Page. So if you give the API a Database id when it wants a Page id, it tells you it doesn't exist. Because a database is not a page. Hence, we have a Kestra plugin for Pages and a separate one for Databases now!&lt;/p&gt;

&lt;p&gt;The Notion API makes you use UUIDs, but the value you need is presented in the URL if you are looking at Notion in a browser... but you need to turn that into a UUID. So my search history looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgbv0lx46m005brnlq5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgbv0lx46m005brnlq5m.png" alt="A Google Search bar and AI summary turning a string of characters into a UUID format" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also use Google Search to do calculations because I could not be bothered to open the calculator app when I'm already in a browser. Follow me for more tips on what Google Search can do. 😂&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiukkyaoze64fbmvqqsgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiukkyaoze64fbmvqqsgi.png" alt="The Kestra flow code editor and topology panels open to show the completed (for now) demo" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I needed a list of CVEs, so I went out to CISA and found their &lt;a href="https://www.cisa.gov/known-exploited-vulnerabilities-catalog" rel="noopener noreferrer"&gt;Known Exploited Vulnerabilities Catalog&lt;/a&gt;. They make this available in a few formats, so I found it in &lt;a href="https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json" rel="noopener noreferrer"&gt;JSON&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The objects are pretty clean and tidy and look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cveID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CVE-2026-33017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vendorProject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Langflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Langflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vulnerabilityName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Langflow Code Injection Vulnerability"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dateAdded"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-03-25"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"shortDescription"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Langflow contains a code injection vulnerability that could allow building public flows without requiring authentication."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"requiredAction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dueDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-04-08"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"knownRansomwareCampaignUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https:&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="s2"&gt;github.com&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;langflow-ai&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;langflow&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;security&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;advisories&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;GHSA-vwmf-pq79-vjvx ; https:&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="s2"&gt;nvd.nist.gov&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;vuln&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;detail&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;CVE-2026-33017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cwes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"CWE-94"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"CWE-95"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"CWE-306"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CVEs are kind of notorious for being hard to understand. They can pop up randomly and the anxiety that comes with trying to decide if your codebase is impacted, plus how fast you need to mitigate them, can make things harder than necessary. So I wanted to augment this a bit and sprinkle in some AI to help. I want Gemini to help me set the priority and action plan and hopefully make it a little easier for a human to parse than the CVE itself.&lt;/p&gt;

&lt;p&gt;I want to pass &lt;em&gt;new&lt;/em&gt; vulnerabilities to AI because, as of writing this, the list is &lt;strong&gt;1557 CVEs&lt;/strong&gt; long and I want to be conscious of token use. I also think it's more realistic for my demo to have a smallish subset of CVEs to triage. &lt;/p&gt;

&lt;p&gt;Once I have this, I want to send it to a Notion Database, where I can have a nice little visual table to assign a human reviewer and create a Notion Page on the specific CVE to capture any implementation details or other notes the human wants to provide for more context on how this applies (or doesn't apply) to us. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F329grbjguct486hkf97e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F329grbjguct486hkf97e.png" alt="A screenshot of the Notion Database for CVE tracking with 4 items" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More on the design
&lt;/h2&gt;

&lt;p&gt;I should start by saying, as always, I'm not looking to make highly performant, production-ready demos. There are times I want to do something less than ideal to show particular aspects or features of the product and workflow mechanics. The things I make should spark a conversation or ideation. Besides, you know your use case better than I do.&lt;/p&gt;

&lt;p&gt;Now that I got the disclaimer out of the way, let's talk about the design of this demo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Store individual CVE IDs in KV Store
&lt;/h3&gt;

&lt;p&gt;I wanted to store the known CVE IDs in a way that was searchable within Kestra, and to do that I used the &lt;a href="https://go.kestra.io/THnUJV" rel="noopener noreferrer"&gt;KV Store&lt;/a&gt;. The keys map to the CVE IDs and the values are the names. The CVE IDs will always be a specific format, but the names could be quite lengthy. However, I could see a case where I need to reference both in my demo.&lt;/p&gt;

&lt;p&gt;This searchability within Kestra gives an admin a fast way to reference whether this is a known CVE in the system since the table in Notion will only show &lt;em&gt;new&lt;/em&gt; known CVEs. &lt;/p&gt;

&lt;h3&gt;
  
  
  Iterate through the JSON
&lt;/h3&gt;

&lt;p&gt;Since I have this running during off hours, I don't really care how long it takes. With 1500+ CVEs to iterate through, this takes about 20-30 minutes with the concurrency limit set to run some tasks in parallel (&lt;code&gt;5&lt;/code&gt;). Without setting the concurrency limit and just letting this default to running everything sequentially, it takes over an hour. Again, running off hours, I could easily tolerate this.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I'm always like &lt;strong&gt;HOW DO I MAKE THIS EVEN BIGGER&lt;/strong&gt;. What more can I pack into this demo?&lt;/p&gt;

&lt;h3&gt;
  
  
  Could I just iterate over the top of the JSON?
&lt;/h3&gt;

&lt;p&gt;Rethinking how I iterate over the JSON. CVEs don't get reported every day, and sometimes multiple get reported in a single day. I could probably be smarter with the iteration and only "read" until I hit a known CVE in my system and then stop since CVEs are added to the top of the JSON response.&lt;/p&gt;

&lt;p&gt;However, if I wanted to build a really robust example and look for &lt;em&gt;any&lt;/em&gt; edits or updates to the CVE information (like whether there is a new known ransomware campaign) I would still need to iterate through all of them.&lt;/p&gt;

&lt;p&gt;This assumes that the behavior I'm seeing, where the CVEs are added to the top of the JSON, is the typical practice. Since I've only been working with this list for ~4 days, this seems typical. &lt;/p&gt;

&lt;p&gt;How would you approach this?&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-populate Notion pages with more CVE info
&lt;/h3&gt;

&lt;p&gt;I want to pre-populate the page with more info from the CVE. When I add a new item to the database, I get the page id returned. I could then take this page id and send over some content with the rest of the info in the JSON. In the execution outputs, I actually have all that info returned in the Database &lt;code&gt;CreateItem&lt;/code&gt; task, so this would be quite trivial. They even give me the page ID as a UUID!!!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Oops, found a bug
&lt;/h3&gt;

&lt;p&gt;I wanted to add a checkbox about whether it should be mitigated now. To me, this is different than priority, but more of an urgency indicator. There's a bug with the Notion Database plugin where I couldn't pass in a boolean, so I removed the checkbox for now. &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;If you want to view or use &lt;a href="https://github.com/akeller/kestra-demos/blob/main/cve_checker.yaml" rel="noopener noreferrer"&gt;this example&lt;/a&gt; you can find it over on GitHub. I do not recommend running it the first time with the AI and Notion tasks enabled because you'll get &lt;strong&gt;1557+ CVEs&lt;/strong&gt; run through Gemini and added to your Notion database. Comment those out for the first run.&lt;/p&gt;

&lt;p&gt;In fact, as I was building this demo the last ~4 days, the CVEs trickled in at a near perfect rate for me to see 1-3 pop into the table, but often I would have to delete a KV item manually to ensure I could get something to populate in my table. &lt;/p&gt;

&lt;p&gt;If you use it as inspiration, let me know what you are building, or what you want to build! Keen eyes will notice I used Kestra EE, but you could definitely build this with Kestra OSS too with a few tweaks for things like secret management. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>orchestration</category>
      <category>security</category>
    </item>
    <item>
      <title>Reflecting on "dead" communities, engagement, and AI</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Tue, 31 Mar 2026 18:04:46 +0000</pubDate>
      <link>https://dev.to/missamarakay/reflecting-on-dead-communities-engagement-and-ai-19hi</link>
      <guid>https://dev.to/missamarakay/reflecting-on-dead-communities-engagement-and-ai-19hi</guid>
      <description>&lt;p&gt;&lt;em&gt;Admittedly this is a bit ranty, and if that's not your jam, feel free to skip.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I stopped scrolling most social media feeds when the slop arrived. First it came in the form of images, big awkward hero images that were psychedelic or had too many arms and fingers. Then it shifted to listicle after listicle. Then the articles that inserted a new line after every... single... sentence.&lt;/p&gt;

&lt;p&gt;I was over it. &lt;/p&gt;

&lt;p&gt;The personal voice and opinions were gone. The images were uncomfortably odd for my brain to process. The attention grabbing tactics were at an all time high and it just wasn't doing it for me anymore. &lt;/p&gt;

&lt;p&gt;So I stopped scrolling. The community that existed on those platforms were dead to me.&lt;/p&gt;

&lt;p&gt;This means I missed things like your promotion or new job or even some significant tech news. Eventually the important things did find me, but I never found myself &lt;em&gt;missing&lt;/em&gt; scrolling. I took that energy to engage somewhere else.&lt;/p&gt;

&lt;p&gt;Fast forward to people saying "this community is dead" or "that community has an engagement problem". The "community" has likely been taken over by garbage that doesn't foster engagement, so the people left. Myself included. Communities are living, breathing organisms and when you fill them with trash, they simply cannot thrive. &lt;/p&gt;

&lt;p&gt;This isn't a post to bash on the admins or the moderators, if they even exist on a particular platform, because that's a hard job, and where do you draw the line in this AI-enabled world? You need content, but you also need engaging content. You need engaged users, but you may need to re-engage users who left. Do we even have the tools and understanding to manage this? Do these platforms have community managers or teams evaluating this?&lt;/p&gt;

&lt;p&gt;Now more than ever people are looking for community, on and offline. They crave it for a variety of reasons, but a sense of belonging, trust, and safety remains. They want to be part of something that connects them to other people in a positive way. People will cultivate community spaces when they feel empowered, dare I say emboldened, to do so. Active and engaged participation is the goal, not casual drive-by headline reading. You want people excited and enthusiastic to show up. And show up regularly.&lt;/p&gt;

&lt;p&gt;So why mention this? Why post this? &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Because I love to complain. But mostly if I'm complaining about something, it's because I'm passionate about it. I strongly believe active participants in communities encourage others to do the same - be active participants.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because I think we are over indexing on "communities are dead" and blaming AI. Have you considered that your AI-generated content isn't engaging? Have you considered comments are more important than views, and provoking a discussion is maybe more meaningful? Have you considered you might be the problem, with or without AI? &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;2026 is apparently the year where I'm just going to say "we have to live in community" over and over again until I hear people say it back to me. But it's true! If you want an engaged community, you need to lead by example and cultivate the environment you are looking for. &lt;/p&gt;

&lt;p&gt;Does that mean I'm suggesting you can't use AI in your blogs? No. But it does mean you should evaluate your blogs for engagement, AI or otherwise. Would you read it? Would you comment on it if someone else wrote it? &lt;/p&gt;

&lt;p&gt;Are your actions or participation a value-add? Because we can't put admins, moderators, and community managers solely responsible for supporting healthy communities. There needs to be some level of personal accountability.&lt;/p&gt;

&lt;p&gt;And maybe it's more obvious in offline spaces. You won't attend another meetup or event where you felt unsafe or uncomfortable. So if a weird AI hero image made you uncomfortable, why would you read the content underneath? Are you seeing the connection here?&lt;/p&gt;

&lt;p&gt;So I'm really interested in challenging this idea that a particular community is dead. Is it dead? Did you or do you positively or negatively contribute to it? And what does it mean to you if it's gone forever?&lt;/p&gt;

&lt;p&gt;How important is a community to you? And how actively will you participate going forward?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@mauromora?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;mauro  mora&lt;/a&gt;&lt;/em&gt; on &lt;a href="https://unsplash.com/photos/timelapse-photo-of-people-passing-the-street-31-pOduwZGE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>community</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Are you paying attention to your token use?</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Mon, 23 Mar 2026 13:45:08 +0000</pubDate>
      <link>https://dev.to/missamarakay/are-you-paying-attention-to-your-token-use-5h5n</link>
      <guid>https://dev.to/missamarakay/are-you-paying-attention-to-your-token-use-5h5n</guid>
      <description>&lt;p&gt;Can I get some folks in the comments talking about how closely they monitor their token usage? &lt;/p&gt;

&lt;p&gt;Or if you don't, do you work at a company that provides you unlimited tokens? To specific tools?&lt;/p&gt;

&lt;p&gt;I'm curious to see where people fall on this spectrum.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@cameramandan83?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Dan Dennis&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/brown-round-coins-on-brown-wooden-surface-pZ56pVKd_6c?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What's in a flow?</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Tue, 17 Mar 2026 16:15:27 +0000</pubDate>
      <link>https://dev.to/missamarakay/whats-in-a-flow-532l</link>
      <guid>https://dev.to/missamarakay/whats-in-a-flow-532l</guid>
      <description>&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/ivg5tDgdysA"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;You can orchestrate anything! And therein lies the problem, can you even imagine what your flow could look like? Where do you start? And what components do you include? &lt;/p&gt;

&lt;p&gt;We have a lot of amazing &lt;a href="https://go.kestra.io/GzXbil" rel="noopener noreferrer"&gt;video content on Kestra&lt;/a&gt; where you've probably heard us mention how flows look and what they contain.&lt;/p&gt;

&lt;p&gt;When you are just getting started, it might be hard to really &lt;em&gt;see&lt;/em&gt; what we mean when we say something like "everything has an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;type&lt;/code&gt;", particularly when you are looking at the following Hello World boilerplate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;buffalo_875352&lt;/span&gt;
&lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;company.team&lt;/span&gt;

&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.log.Log&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hello World! 🚀&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like sure, the &lt;em&gt;one&lt;/em&gt; &lt;a href="https://go.kestra.io/aDKXf3" rel="noopener noreferrer"&gt;runnable task&lt;/a&gt; you can see does, indeed, have an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;type&lt;/code&gt;. But is this really important to cover? And why? It's just not really convincing. At least not yet!&lt;/p&gt;

&lt;p&gt;So let's talk through some increasingly complex flows, what components they contain, and get you more familiar with what your next workflow with Kestra could look like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expression syntax &lt;code&gt;{{ }}&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let's increase the complexity from boiler plate and check out my &lt;a href="https://go.kestra.io/rjkn5b" rel="noopener noreferrer"&gt;log_off_flow&lt;/a&gt; and talk about expressions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.kestra.io/EwZ705" rel="noopener noreferrer"&gt;Expression syntax&lt;/a&gt; is critical to passing around information, making flows more dynamic with inputs, and even referencing a particular iteration during something like a &lt;code&gt;ForEach&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.kestra.io/THnUJV" rel="noopener noreferrer"&gt;KV Store&lt;/a&gt; values are pretty straight forward - &lt;code&gt;{{ kv('issues_today') }}&lt;/code&gt;. This simply references the value with the key &lt;code&gt;issues_today&lt;/code&gt;. It's similar for secrets. &lt;/p&gt;

&lt;p&gt;Outputs might be a little more complicated, depending on the type of output - &lt;code&gt;{{ outputs.get_issues.body }}&lt;/code&gt;. This would get the output of the &lt;code&gt;get_issues&lt;/code&gt; task, and specifically the response body of the API request. &lt;/p&gt;

&lt;p&gt;You can also get into some complex filtering and formatting with your expressions - &lt;code&gt;{{ now() | dateAdd(-5, 'DAYS') | date(\"yyyy-MM-dd'T'07:00:00-06:00\") }}&lt;/code&gt;. This is how you would get todays date, but actually 5 days ago and format it in a certain way. &lt;/p&gt;

&lt;h2&gt;
  
  
  Everything really does have an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;type&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Once you hit a certain level of complexity in your workflows, you start nesting tasks. This could be due to flowable tasks where you want to do some sort of branching like parallelism in this snippet from the &lt;code&gt;airbyte-sync-parallel-with-dbt&lt;/code&gt; blueprint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;data_ingestion&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.flow.Parallel&lt;/span&gt;
    &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;salesforce&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12ab&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google_analytics&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12cd&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;facebook_ads&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12ef&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Whether it's a &lt;a href="https://go.kestra.io/ccz5B4" rel="noopener noreferrer"&gt;flowable&lt;/a&gt; or runnable task, it's got (say it with me now): an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;type&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plugin Defaults really do clean up your flow readability
&lt;/h2&gt;

&lt;p&gt;Let's look at that same snippet from the &lt;code&gt;airbyte-sync-parallel-with-dbt&lt;/code&gt; blueprint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;data_ingestion&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.flow.Parallel&lt;/span&gt;
    &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;salesforce&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12ab&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google_analytics&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12cd&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;facebook_ads&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12ef&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You may not realize it, but this set of 3 tasks is using &lt;a href="https://go.kestra.io/yNL9A7" rel="noopener noreferrer"&gt;Plugin Defaults&lt;/a&gt; to cover some additional properties, which you can find further down the flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pluginDefaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:8000/&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_USERNAME')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_PASSWORD')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without them, that snippet would look more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;data_ingestion&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.flow.Parallel&lt;/span&gt;
    &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;salesforce&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12ab&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:8000/&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_USERNAME')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_PASSWORD')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google_analytics&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12cd&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:8000/&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_USERNAME')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_PASSWORD')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;facebook_ads&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.airbyte.connections.Sync&lt;/span&gt;
        &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;e3b1ce92-547c-436f-b1e8-23b6936c12ef&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:8000/&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_USERNAME')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('AIRBYTE_PASSWORD')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;It's the exact same info x3. It's harder to read and if we needed to make an update to say, the URL, we'd be stuck doing it x3. Not great for maintainability, particularly those of us who typo from time-to-time. &lt;/p&gt;

&lt;p&gt;And nothing is stopping you from using Plugin Defaults when you only use the plugin once. Maybe just pulling those values away from the rest of the plugin properties makes it easier to read and modify. Consider adding comments and group those properties to indicate those &lt;em&gt;could&lt;/em&gt; be modified in the future, but don't touch the rest. &lt;/p&gt;

&lt;h2&gt;
  
  
  Order doesn't matter, mostly
&lt;/h2&gt;

&lt;p&gt;I like my &lt;a href="https://go.kestra.io/XWhPvc" rel="noopener noreferrer"&gt;triggers&lt;/a&gt; at the top of my flow code, by default you may see them toward the bottom. Your topology will show them either at the top or on the left side, depending on how you chose to orient your diagram. Placing them at the top of your flow code makes it easier to read and quickly grasp how this flow could start, but if you have the topology panel open, you could quickly reference that just as easily.&lt;/p&gt;

&lt;p&gt;However, your task order &lt;em&gt;can&lt;/em&gt; matter, particularly if you want to pass outputs from one task to the next. &lt;/p&gt;

&lt;p&gt;You may also want to group tasks in such a way that you contain them to a &lt;a href="https://go.kestra.io/bqq7tX" rel="noopener noreferrer"&gt;working directory&lt;/a&gt;. This is particularly important for tasks that clone repos and/or you want to share those files across scripts.&lt;/p&gt;

&lt;p&gt;You can decide what order makes sense to you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Meaningful, short &lt;code&gt;id&lt;/code&gt;s make your topology a better reference
&lt;/h2&gt;

&lt;p&gt;Again, when you are looking at a minimal flow, meaningful &lt;code&gt;id&lt;/code&gt;s don't really click.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2wf9nyxd1r5xwr99eqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2wf9nyxd1r5xwr99eqw.png" alt="Flow code and topology view in Kestra for the Hello World boilerplate with a single task with id "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's clear, you don't have to zoom in or move around, and you can see the log icon super clearly. &lt;/p&gt;

&lt;p&gt;But then you do something more interesting and it looks more like:&lt;/p&gt;

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

&lt;p&gt;And that's an eye chart. Let me zoom in a little and be less dramatic.&lt;/p&gt;

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

&lt;p&gt;The longer the ids, the harder they are to really grasp what's happening in the topology. If you prefer to grasp your flow in the flow code directly, this may be less of a problem for you. But keep this in mind if you have project stakeholders who do rely on the topology and try to give them the best experience you can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errors
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://go.kestra.io/a2xByg" rel="noopener noreferrer"&gt;Errors&lt;/a&gt; can be handled at the flow-level or task-level with the &lt;code&gt;errors&lt;/code&gt; property (which we sometimes refer to as the errors block). Things happen and we want them to fail gracefully or notify the right people or systems to ensure it's handled as gracefully as possible. &lt;/p&gt;

&lt;p&gt;That would look something like this for a flow-level error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout_failure_diagnostics&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.log.Log&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;Rollout failed for tenant={{ inputs.tenant_id }}.&lt;/span&gt;
      &lt;span class="s"&gt;execution={{ execution.id }}.&lt;/span&gt;
      &lt;span class="s"&gt;last_error={{ errorLogs()[0]['message'] }}.&lt;/span&gt;
      &lt;span class="s"&gt;Review the latest [PRE]/[PROBE]/[POST] logs for the failing application.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll probably want to reference what input, &lt;code&gt;{{ inputs.x }}&lt;/code&gt;, may have contributed to the failure along with the execution id, &lt;code&gt;{{ execution.id }}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And if you didn't spot it, the errors property does, in fact, have an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;type&lt;/code&gt;! &lt;/p&gt;

&lt;h2&gt;
  
  
  Flows as Blueprints
&lt;/h2&gt;

&lt;p&gt;All the flows covered in this blog are available as &lt;a href="https://go.kestra.io/C5LB87" rel="noopener noreferrer"&gt;blueprints&lt;/a&gt;, with the exception of the boilerplate that's included every time you create a new flow from scratch. You can find the blueprints below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;log_off_flow (available in two options: Notion or Confluence)

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.kestra.io/rjkn5b" rel="noopener noreferrer"&gt;With Notion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.kestra.io/TARr7a" rel="noopener noreferrer"&gt;With Confluence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://go.kestra.io/UaFWSj" rel="noopener noreferrer"&gt;airbyte-sync-parallel-with-dbt&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://go.kestra.io/X1YzmY" rel="noopener noreferrer"&gt;argocd-single-tenant-wave-rollout&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;You can also find them in the Blueprints menu directly in the Kestra UI, where you can copy or click the "Use" button and use it yourself. &lt;/p&gt;




&lt;p&gt;I hope you enjoyed this walkthrough of different flow components and flows with increasing complexity. I added tons of links so you can go a little deeper on certain topics as you see fit. &lt;/p&gt;

&lt;p&gt;Let me know what you want to see next with Kestra in the comments or come join our community! &lt;/p&gt;

</description>
      <category>automation</category>
      <category>beginners</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Workshopping my "Anatomy of a Kestra Flow" video idea</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Tue, 10 Mar 2026 18:21:34 +0000</pubDate>
      <link>https://dev.to/missamarakay/workshopping-my-anatomy-of-a-kestra-flow-video-idea-d8h</link>
      <guid>https://dev.to/missamarakay/workshopping-my-anatomy-of-a-kestra-flow-video-idea-d8h</guid>
      <description>&lt;p&gt;I pulled together a quick video where I step through 4 different workflows and kind of talk through some ideas I had for more of a polished video. Let me know what you'd like me to focus on or where I should go into more details!&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/t7FBaDudx7c"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>automation</category>
      <category>discuss</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>What should I do and learn in 2026?</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Mon, 02 Mar 2026 19:31:11 +0000</pubDate>
      <link>https://dev.to/missamarakay/what-should-i-do-and-learn-in-2026-4enc</link>
      <guid>https://dev.to/missamarakay/what-should-i-do-and-learn-in-2026-4enc</guid>
      <description>&lt;p&gt;I blinked and it's March. That's not entirely true, January was 100 years long, then February showed up, and at least here in Central Texas, that meant it was harshly cold for like 48 hours and now it's summer. "That's false Spring!" No... we don't have Spring here. &lt;/p&gt;

&lt;p&gt;Anyway, &lt;strong&gt;it's March&lt;/strong&gt; and you might be asking yourself what you should actually be doing this year now that the year is rolling onward. You may have yearly or quarterly goals or metrics, but what are your personal development goals? And do you already feel behind?&lt;/p&gt;

&lt;p&gt;You may be asking yourself what you want to actually &lt;em&gt;do&lt;/em&gt; this year. What do you want to learn? What skills do you want to level up? Never fear, let me provide you with my opinionated list of some of the tactics I recommend for navigating this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use AI and have opinions about popular AI tools
&lt;/h2&gt;

&lt;p&gt;I want to be very clear that I don't think AI is appropriate &lt;em&gt;everywhere&lt;/em&gt;, but I do think if you are in tech you need to have some kind of personal narrative around AI, particularly related to your role. Where you use it, why, and how.&lt;/p&gt;

&lt;p&gt;Someone recently asked if I would let AI write blogs for me, and the answer is &lt;strong&gt;no&lt;/strong&gt;, I barely let any tools spell and grammar check my blogs. I'm sure you can tell. Voice and style aside, which I'm aware an AI can "learn", I find writing very cathartic and if someone else reads and enjoys it, that's a bonus. I have no reason to give that up, but also, where am I going to put this chaotic, GIF-filled corporate rage? &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPWVjZjA1ZTQ3eTN6OHdxeDVpdDI0MmpzZWprenBvODI1ZDlld3M3eWl3MDE5d2F1MiZlcD12MV9naWZzX3NlYXJjaCZjdD1n/8YEeD1WB5FeyAiONoe/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPWVjZjA1ZTQ3eTN6OHdxeDVpdDI0MmpzZWprenBvODI1ZDlld3M3eWl3MDE5d2F1MiZlcD12MV9naWZzX3NlYXJjaCZjdD1n/8YEeD1WB5FeyAiONoe/giphy.gif" alt="Schitt's Creek's Alexis going " width="427" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I digress. &lt;/p&gt;

&lt;h3&gt;
  
  
  Claude for summarizing, brainstorming, and ideation
&lt;/h3&gt;

&lt;p&gt;I use Claude for summarizing written content for things like video scripts. My prompts are dead simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Turn this blog into a 2-3 minute video script.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude and I also like to collaborate on talk ideas, titles, and descriptions. This gives me a great base to either edit on my own, entirely rework, or read exactly once and close Claude's window. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make this talk title something people would actually go to.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also like asking for summaries on specific docs pages because I want to see a TL;DR that matches my understanding. This leads into the next use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docs AI for search and knowledge checks
&lt;/h3&gt;

&lt;p&gt;I use built-in docs AI for enhanced search and knowledge checks, almost like quizzes in academy courses. Those implementations will heavily depend on the model, but many are good about citing their sources if I feel like I need to fact check.&lt;/p&gt;

&lt;p&gt;If there is both a search and a docs AI, I like to see what results come up when I search or ask a question with similar terms. This is helpful to see and work to improve the UX and "findability" within docs. If search and docs AI are generating different results, or worse, they are not finding what they should, you need to spend some time to fix it before your users get stuck.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copilots
&lt;/h3&gt;

&lt;p&gt;I'm mostly only working on small code bases and demos these days, so I can use Kestra's Copilot or Visual Studio Code's Copilot, something specific to a single file or repo, and this works really well for me. I know some people have other AI agents deep in their organization's tooling, but I don't really need that right now. &lt;/p&gt;

&lt;p&gt;All of this comes back to my experience with AI and my opinions I've developed around it. These options may not work for you, but I would strongly encourage you to develop your own experience and opinions, particularly because it will come up in my next "skill": interviewing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Never stop interviewing
&lt;/h2&gt;

&lt;p&gt;This one hurts to type because interviewing is hard, even in the most pleasant interview cycles and job markets. It can evoke a lot of negative feelings and, depending on who you talk to about it, might make it seem like you &lt;em&gt;are&lt;/em&gt; looking for your next opportunity. How you feel after that interview, whether you are truly job seeking or not, can be largely dependent on the interviewer. &lt;/p&gt;

&lt;p&gt;The idea with this one is you "never stop interviewing" so you never lose the skills to interview. You are able to talk about your experience, skills, delivery, and value outside of a yearly or bi-yearly performance review to someone who knows nothing other than maybe what you put on the application and in your resume. &lt;/p&gt;

&lt;p&gt;I heard this one very early on in my career from someone quite senior, and then I heard it reinforced by people in other areas of the org chart. They were clear that they weren't necessarily looking for another position, but they wanted to know what was out there and they wanted to keep these interview skills honed.&lt;/p&gt;

&lt;p&gt;It's also a great reality check to see if you need to do a hard pivot of some kind. Sometimes titles change or roles evolve and you need to be flexible enough to adjust. Interviewing helps you understand what people outside of your current organization are looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep your resume updated
&lt;/h2&gt;

&lt;p&gt;I like to visit my resume at least twice a year, typically aligned either with a performance review or the end of the year. What you are trying to avoid is a situation where you &lt;em&gt;need&lt;/em&gt; an updated resume immediately, and you can't possibly figure out how to summarize your role on the fly. &lt;/p&gt;

&lt;p&gt;If you can get really good at having a refined, ready-to-go resume, you should be really good at communicating your role, experience, skills, delivery, value, etc. and interviewing (and performance reviews!) become easier too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find your community, online and offline
&lt;/h2&gt;

&lt;p&gt;I started going to bookstore events last year. I had started reading romance novels for the predictability and comfort that comes with a happily ever after (HEA) or happy for now (HFN). And at some point I realized one of my favorite authors was local and I could actually go see her. And surround myself with people who also thought she and her books were pretty cool too. Not only do these events immediately feel like safe spaces, they remind me that even though I've spent an entire career working mostly with men, there are communities that are almost entirely not-men out there too. &lt;/p&gt;

&lt;p&gt;And it's all about finding balance. Like balancing a stack of books on the way to the cash register when you just came for one. Oopsies!&lt;/p&gt;

&lt;p&gt;More and more community spaces and groups seem to be seeing a post-pandemic-shutdown renaissance. I don't know exactly what's driving that, but I know I'm finding more energy to even get out to tech meetups again. Maybe people are craving those connections again? This makes it a great time to join and explore communities with others doing the exact same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Geek out on something
&lt;/h2&gt;

&lt;p&gt;I like birds. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2ypohwr04ndawdy71x3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2ypohwr04ndawdy71x3.gif" alt="Zombie kid saying " width="499" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not new, this is a life long... hobby...? Birds + AI are apparently a thing this year, with CES summoning AI-powered bird identifying tools. So I acquired some new tech and apps to live my best bird nerd life this year. &lt;/p&gt;

&lt;p&gt;Birds aren't your thing? Find something to go deep into. I'm also big into nail polish and stained glass (copper foil &amp;amp; lead came). Those aren't even close to tech adjacent, but they give me an opportunity to "touch grass" away from a computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what's the plan?
&lt;/h2&gt;

&lt;p&gt;Maybe this wasn't quite the list you were expecting, but I hope it gets you thinking. What is on your list for doing and learning this year? Have you started? There is still so much year left.&lt;/p&gt;

</description>
      <category>career</category>
      <category>learning</category>
      <category>motivation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What even is orchestration?</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Thu, 19 Feb 2026 20:38:23 +0000</pubDate>
      <link>https://dev.to/missamarakay/what-even-is-orchestration-161o</link>
      <guid>https://dev.to/missamarakay/what-even-is-orchestration-161o</guid>
      <description>&lt;p&gt;I accidentally ended up in the process automation and orchestration space when I started my career, and somehow even more accidentally I'm still there. As Taylor Swift says, "help, I'm still at the restaurant."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex0vy841arb47egpnoha.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex0vy841arb47egpnoha.gif" alt="Taylor Swift waving to the crowd at the beginning of the Eras Tour" width="480" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Being in the enterprise software space this long, I feel like the pendulum has swung back and forth between "buy a full suite platform, it has everything you need" and "avoid vendor lock-in" and something in between. AI has certainly left it's mark, but hasn't changed things all that dramatically.&lt;/p&gt;

&lt;p&gt;You'll find people and companies saying you need a specialized purpose-built platform with a very specific set of use cases or personas or one that's agnostic and fits any and all needs.&lt;/p&gt;

&lt;p&gt;It's no different in the process automation and orchestration space. &lt;/p&gt;

&lt;p&gt;All of this to say, we still have the same problem - this separation in ownership and responsibilities from the thing we want to improve and how it's actually going to be improved. You often here this positioned as "the business" and "the development team". "The business" gets pitched as this non-technical group of diagram drawing, process optimizing suits while "the development team" adds the code and system integrations to make the diagram actually work, but doesn't &lt;em&gt;own&lt;/em&gt; the process.&lt;/p&gt;

&lt;p&gt;I still look back on my early career days and remember our business partner asking if she could just give me a Visio diagram and could I turn that into BPMN for her because the standards were too technical. BPMN... as in the standards that were supposed to be the literal language that filled this "gap" between "the business" and "the development team"... was too technical. Interesting. &lt;/p&gt;

&lt;p&gt;I have this hypothesis that people in tech generally understand process automation and why it's beneficial, but only certain areas and roles within tech seem to really resonate with the term "orchestration". So maybe let's talk about that a bit and give you a few examples of where orchestration really shines. Then you can tell me your definition. &lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, so what is orchestration?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdejzyuddr8c9weepqcm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdejzyuddr8c9weepqcm.gif" alt="A broad zoom in on a conductor of a string orchestra" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You would think it's overdone, but the analogy of a conductor with an orchestra really fits here. You have a bunch of different instruments kind of doing their own thing, but together, with the help of a conductor, making a beautiful coherent piece of music happen. They get clues on when to speed up, slow down, or when to play with more or less intensity. &lt;/p&gt;

&lt;p&gt;But I can see how that doesn't translate super well to tech.&lt;/p&gt;

&lt;p&gt;Let's get some help from the internets. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Orchestration is the coordinated execution of multiple IT automation tasks or processes. Orchestration is usually applied across multiple computer systems, applications, and services to ensure that deployment, configuration management, and other processes are performed in the proper sequence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Via RedHat&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Orchestration is the coordination and management of multiple computer systems, applications and/or services, stringing together multiple tasks in order to execute a larger workflow or process. More specifically, orchestration is the coordinated execution of multiple IT automation tasks or processes across multiple computer systems, applications and services. These processes can consist of multiple tasks that are automated and can involve multiple systems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Via Databricks&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Orchestration is the process of coordinating distributed software components and systems so that they execute seamlessly as an automated, repeatable process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Via Orkes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These definitions read a lot like the DevOps definitions - multiple systems, coordination, working together with automation, etc.&lt;/p&gt;

&lt;p&gt;Basically, anytime you want to do something complex and chain together a sequence of tasks or coordinate and manage multiple systems, applications, or services either ad-hoc, scheduled, or when &lt;em&gt;something&lt;/em&gt; happens &lt;em&gt;somewhere&lt;/em&gt; you probably want to do it in a clear and reusable way with orchestration. Got it? So clear!&lt;/p&gt;

&lt;p&gt;You'll see orchestration and automation together quite often, but it's typically positioned around the involvement of humans where automation is helping humans, without intervention, complete a single task. Orchestration tends to be more complex, but may involve humans (human-in-the-loop). To what extent humans participate depends. &lt;/p&gt;

&lt;h2&gt;
  
  
  I think I get it, but I need examples...
&lt;/h2&gt;

&lt;p&gt;Let's try to make this a little more tangible. &lt;/p&gt;

&lt;h3&gt;
  
  
  Data Orchestration
&lt;/h3&gt;

&lt;p&gt;You have data everywhere, in multiple disparate systems, and now you want to do something with it. Very everything, everywhere, all at once. This is where you see data pipelines, ETL, etc. come into play. You don't necessarily want to merge all the data together into one big database, but you do want to coordinate across the systems to, say, use the data to make informed decisions. &lt;/p&gt;

&lt;h3&gt;
  
  
  Business Orchestration
&lt;/h3&gt;

&lt;p&gt;This tends to be where process automation and orchestration live in the traditional IT, HR, and finance workflows. My favorite example in this space is a two-step approval process, because it involved a human-in-the-loop aspect (maybe even two!), but many people have seen this at work or in their personal life. &lt;/p&gt;

&lt;p&gt;If you know what "signature authority" is you've definitely been a part of a process like this, and the larger the organization, the more systems might be involved to make decisions.&lt;/p&gt;

&lt;p&gt;You may encounter a set of rules that fast track you through the process (like my "signature authority" was once $100, which was basically desk trinkets) and anything more than that was escalated to my manager until his "signature authority" limit was hit and then it escalated to his manager. So this system needs to know the org chart, the individuals' "signature authority", the price of the items to be purchased, etc. All of that info is definitely in different databases, if not completely different systems.  &lt;/p&gt;

&lt;h3&gt;
  
  
  AI Orchestration
&lt;/h3&gt;

&lt;p&gt;This is relatively new and gets us into murky territory as well. Agent orchestration, multi-agent systems (MAS), AI pipelines can all fall into this bucket of AI orchestration. MAS for me is really the foundation for where we are at now with AI agents and potentially having them do coordinated work together.&lt;/p&gt;

&lt;p&gt;The agents need data, then with that data they do something with other agents, and something complex happens. &lt;/p&gt;

&lt;p&gt;I'm intentionally being a bit handwavy here because I don't have a great real world example of this yet, just a lot of marketing blogs around specialized agents working together to complete a common goal. &lt;/p&gt;

&lt;h2&gt;
  
  
  But when do you need an orchestrator?
&lt;/h2&gt;

&lt;p&gt;It depends, of course. &lt;/p&gt;

&lt;p&gt;Some organizations will start building some stitched together, homegrown solution and ultimately hit a point where there is a maintenance or scale issue. Others will realize they want to do something beyond CRON and scheduled jobs, something more real-time and event-based where they need listeners or webhooks.&lt;/p&gt;

&lt;p&gt;Others still will realize they need to do a mix of scheduled, event-based, and manual executions with responsibilities spanning across technical and non-technical roles, and this is usually when they start investigating platforms to handle some of this. &lt;/p&gt;

&lt;h2&gt;
  
  
  So, how do you define orchestration?
&lt;/h2&gt;

&lt;p&gt;Hopefully, I've given you a bit to think about and start to formulate your own opinion on orchestration. &lt;/p&gt;

&lt;p&gt;What's your definition of orchestration? Are you doing orchestration within your organization? And how did you evaluate your options? &lt;/p&gt;

&lt;h2&gt;
  
  
  Sources &amp;amp; further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.redhat.com/en/topics/automation/what-is-orchestration" rel="noopener noreferrer"&gt;https://www.redhat.com/en/topics/automation/what-is-orchestration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.databricks.com/glossary/orchestration" rel="noopener noreferrer"&gt;https://www.databricks.com/glossary/orchestration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.prefect.io/blog/what-i-talk-about-when-i-talk-about-orchestration" rel="noopener noreferrer"&gt;https://www.prefect.io/blog/what-i-talk-about-when-i-talk-about-orchestration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kestra.io/blogs/orchestration-differences" rel="noopener noreferrer"&gt;https://kestra.io/blogs/orchestration-differences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://orkes.io/blog/what-is-orchestration/" rel="noopener noreferrer"&gt;https://orkes.io/blog/what-is-orchestration/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>processautomation</category>
      <category>bpmn</category>
    </item>
    <item>
      <title>Wrapping up my first Kestra flow</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Fri, 06 Feb 2026 17:33:13 +0000</pubDate>
      <link>https://dev.to/missamarakay/wrapping-up-my-first-kestra-flow-4o9h</link>
      <guid>https://dev.to/missamarakay/wrapping-up-my-first-kestra-flow-4o9h</guid>
      <description>&lt;p&gt;We've reach the end of the lovely saga of learning this has been creating my "first flow" in Kestra. So let's walkthrough what I did and what you can do.&lt;/p&gt;

&lt;p&gt;I got it all to fit in a nice, clean topology!&lt;/p&gt;

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

&lt;p&gt;And here's a complete gist so we don't have to fight formatting and spacing issues:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;h2&gt;
  
  
  Why is my trigger at the top?
&lt;/h2&gt;

&lt;p&gt;I want to be able to easily see what triggers this workflow without scrolling to the bottom of the YAML file. For me, this is a "best practice" I'll continue to do. Your triggers may get added to the bottom, but order doesn't matter and you can move them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use the HTTP Request plugin and not the GitHub plugin?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get_issues&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.http.Request&lt;/span&gt;
    &lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.github.com/orgs/kestra-io/issues?filter=assigned&amp;amp;state=closed&amp;amp;since={{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;now()&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dateAdd(-5,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'DAYS')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;date(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;yyyy-MM-dd'T'07:00:00-06:00&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('CLASSIC_GITHUB')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/vnd.github+json&lt;/span&gt;
      &lt;span class="na"&gt;X-GitHub-Api-Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2022-11-28&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As of writing this post, the &lt;a href="https://go.kestra.io/TQQ06y" rel="noopener noreferrer"&gt;GitHub plugin&lt;/a&gt; returns &lt;code&gt;.ion&lt;/code&gt; files and I didn't want to work with files with such a (relatively) small anticipated dataset. I just wanted JSON, which the &lt;a href="https://go.kestra.io/qZyRJT" rel="noopener noreferrer"&gt;HTTP Request plugin&lt;/a&gt; gives me easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expressions and filters
&lt;/h2&gt;

&lt;p&gt;This remains my favorite expression I've crafted so far: &lt;/p&gt;

&lt;p&gt;"Now, but five days ago, and formatted"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;now() | dateAdd(-5&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DAYS'&lt;/span&gt;&lt;span class="nv"&gt;) | date(\"yyyy-MM-dd'T'07&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;00&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;00-06&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;00\")&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would have like to create something a bit "smarter" here and detect the first working day of the week or &lt;em&gt;the Monday of that week&lt;/em&gt; but I kind of made an assumption I would run this on Fridays only.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ForEach&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You'll notice I left the returns in both &lt;code&gt;ForEach&lt;/code&gt; blocks. I didn't really have a creative idea for this information but I did want to use this as an opportunity to play around with the context within a &lt;code&gt;ForEach&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As I mentioned in a previous blog, my company's Google Calendar settings prevent me from &lt;em&gt;seeing&lt;/em&gt; any of the more interesting calendar information, and my browser(?) settings seem to prevent the returned link from grabbing focus on my calendar. Any meeting link I click just sends me to the current time, which doesn't really do anything for me. &lt;/p&gt;

&lt;h2&gt;
  
  
  New Blueprints for you to use!
&lt;/h2&gt;

&lt;p&gt;I created two &lt;a href="https://go.kestra.io/C5LB87" rel="noopener noreferrer"&gt;Blueprints&lt;/a&gt; based off my first flow that you can use as a starting point, one for Confluence and one for Notion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.kestra.io/AHtvNV" rel="noopener noreferrer"&gt;Weekly Confluence Recap Blueprint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.kestra.io/4inrx8" rel="noopener noreferrer"&gt;Weekly Notion Recap Blueprint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are cleaned up from my original flow and don't include random logs and outputs.&lt;/p&gt;

&lt;p&gt;You'll need to plug in your Confluence or Notion instance info, like the API tokens, page ids, etc. I've also adjusted them to save you from character escaping hell with the Slack plugin by using &lt;code&gt;messageText&lt;/code&gt; instead of &lt;code&gt;payload&lt;/code&gt;. &lt;code&gt;messageText&lt;/code&gt; will handle markdown for you. &lt;/p&gt;

&lt;p&gt;It also just looks cleaner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_to_slack&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.slack.SlackIncomingWebhook&lt;/span&gt;
    &lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('SLACK_WEBHOOK')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
    &lt;span class="na"&gt;messageText&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;went&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kv('meetings_today')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;meetings&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kv('issues_today')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PR(s)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;issue(s)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Kestra&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;org!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, if you have to choose, I would pick the Notion plugin for the easier experience. Not having to pass back the version number exactly incremented by 1 is faster and easier, particularly if you may want to manually add info to supplement what's getting passed in via your workflow. I get that Confluence wants to keep track of version history, but this was one of those annoying UX gotchas for me while I was testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I use Blueprints?
&lt;/h2&gt;

&lt;p&gt;There are a few ways to do this depending where you are and how many browsers or tabs you have opened.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy my gist above and add it to your flow code editor. It's nearly a Blueprint anyway.&lt;/li&gt;
&lt;li&gt;Access Blueprints directly in a panel adjacent to your flow code editor and click copy, then add to your flow code editor.&lt;/li&gt;
&lt;li&gt;Click the "Blueprints" tab on the left-side menu then Flow Blueprints and click the "Use" button. This will automatically create a new flow with the Blueprint.&lt;/li&gt;
&lt;li&gt;Find the Blueprint on the &lt;a href="https://go.kestra.io/C5LB87" rel="noopener noreferrer"&gt;Blueprints website page&lt;/a&gt; and click the "Copy source code" button, then add to your flow code editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So, now what?
&lt;/h2&gt;

&lt;p&gt;I guess I can officially declare my "first flow" with Kestra complete! It's been refined and refactored quite a bit, and while it doesn't do exactly what I hoped it would do, it was a great learning experience that I'm happy to share with you.&lt;/p&gt;

&lt;p&gt;What should I tackle next? What do you want to learn about Kestra? &lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@tobias_carl?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Tobias Carlsson&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/multicolored-light-passage-in-dark-area-d3Zu34NBg7A?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>workflows</category>
    </item>
    <item>
      <title>Tips and tricks for your Kestra flows</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Tue, 20 Jan 2026 20:35:41 +0000</pubDate>
      <link>https://dev.to/missamarakay/tips-and-tricks-for-your-kestra-flows-40ei</link>
      <guid>https://dev.to/missamarakay/tips-and-tricks-for-your-kestra-flows-40ei</guid>
      <description>&lt;p&gt;Maybe you've read my multi-part series (&lt;a href="https://dev.to/missamarakay/my-first-flow-with-kestraio-31g9"&gt;part 1&lt;/a&gt;, &lt;a href="https://dev.to/missamarakay/more-adventures-in-building-a-first-flow-with-kestraio-11ib"&gt;part 2&lt;/a&gt;) about building my first &lt;a href="https://go.kestra.io/k91sTC" rel="noopener noreferrer"&gt;Kestra&lt;/a&gt; flow? Maybe you noticed I made it overly complicated. But here is where you benefit! I have tons of tips and tricks for you.&lt;/p&gt;

&lt;p&gt;Just like any list of tips and tricks, some will be a technical requirements while others will be a preference. If you prefer something different, that's totally fine and I'd love to hear about it in the comments.&lt;/p&gt;

&lt;p&gt;Let's dig in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Name your flow id something relevant
&lt;/h2&gt;

&lt;p&gt;Out-of-the-box, you are going to get something auto generated as your flow id that has no relation or relevance to your flow. Change it before you save your flow or you'll need to make a new flow. &lt;/p&gt;

&lt;p&gt;Do you know what &lt;code&gt;lyrebird_805364&lt;/code&gt; is? Neither do I, so I have to click into it to refresh my memory. It's my small example flow for debugging Confluence version info and passing an expression as a number. Obviously. &lt;/p&gt;

&lt;p&gt;The id must be unique and, like mentioned above, it's immutable, so if you forget, you'll need to create a new flow with the id you actually want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep your YAML readable
&lt;/h2&gt;

&lt;p&gt;One of the biggest benefits of YAML is the human-readable nature, but you can quickly make your YAML really messy, whether it's YAML for a Kestra workflow or something else. &lt;/p&gt;

&lt;p&gt;Remember you can add comments and spaces to keep your YAML readable. I like to think about it almost like a blog, I want to be able to read it top to bottom with some amount of structure, and that includes blocks separated by spaces. &lt;/p&gt;

&lt;h2&gt;
  
  
  Triggers at the top
&lt;/h2&gt;

&lt;p&gt;Most ordering of information in your flow code doesn't really matter, but when you take into account the human-readable aspects of YAML, I like having my triggers at the top of my file just like I read top to bottom, down the page. Without having to look anywhere else, I can see exactly what triggers the rest of the flow. &lt;/p&gt;

&lt;p&gt;Similarly, I put outputs on the bottom, but admittedly, I've only done trivial things with outputs, which is why I didn't call this out as a separate tip. Where would you put your flow outputs? Top? Bottom? Depends?&lt;/p&gt;

&lt;h2&gt;
  
  
  Chunk it up during development
&lt;/h2&gt;

&lt;p&gt;If you know you are going to build a large or complex flow, as you piece it together, consider building in chunks in separate flows or using comments. &lt;/p&gt;

&lt;p&gt;As my "first flow" got bigger and bigger, I wanted to focus on the part that was new or the plugin that wasn't quite working yet. Sometimes I would pull chunks up to the top of the flow so they ran first, or comment out sections I knew were working, or even create a new, small flow with a single plugin to remove any other variables that might be making something not work as expected. &lt;/p&gt;

&lt;p&gt;My favorite keyboard shortcut is commenting/uncommenting large blocks with &lt;code&gt;option&lt;/code&gt; + &lt;code&gt;/&lt;/code&gt; (on Mac at least). Hit the &lt;code&gt;...&lt;/code&gt; menu in your flow code editor and find the rest of the keyboard shortcuts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secrets need to stay secret
&lt;/h2&gt;

&lt;p&gt;I am one of those &lt;em&gt;notoriously&lt;/em&gt; lazy developers who just slaps credentials in plain text, particularly if I'm developing PoCs locally. Who is going to see it? My cat? &lt;/p&gt;

&lt;p&gt;Revisions are created with every save, so if this PoC does evolve into something bigger, your credentials are certainly in a revision, maybe even several. You could go through and delete revisions, but using environment variables or the EE Secrets will save you a lot of annoyances.&lt;/p&gt;

&lt;p&gt;Don't be like me and hide your secrets from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try the No-code experience
&lt;/h2&gt;

&lt;p&gt;Even if you are a hardcore developer, the no-code experience is pretty neat. If nothing else, it's cool to see what you could add to your flow and the changes propagate in both directions, so you can shift back and forth between flow code and no-code.&lt;/p&gt;

&lt;p&gt;The no-code editor also shows me the type for each property which I find a little bit easier to parse than the documentation window at times. &lt;/p&gt;

&lt;p&gt;If I had a bigger monitor I might consider keeping the flow code, no-code and documentation windows all open at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plugins are evolving
&lt;/h2&gt;

&lt;p&gt;Some of the plugins are incredibly new and specific to a single use case or flow. If they use 3rd party APIs, they may not include all endpoints or all APIs for a given technology. Between the very engaged group of contributors and passionate Kestra employees, if you see something that doesn't work or doesn't work the way you want it to, simply create an issue for a bug or feature request. It will get triaged and addressed. But what we don't know, we can't fix!&lt;/p&gt;

&lt;p&gt;Similarly, if you see an integration is missing, you can create a plugin yourself. The flexibility here is great.&lt;/p&gt;

&lt;p&gt;EE users can also update plugins directly in the UI, which I did several times as new updates extended functionality or fixed bugs. &lt;/p&gt;

&lt;p&gt;Did I miss a tip or trick that's your favorite? Let me know in the comments. And as always, I'd love to know what you are building with Kestra so give me a shout! &lt;/p&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@tma?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Tianyi Ma&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/macbook-pro-on-white-surface-WiONHd_zYI4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>workflows</category>
    </item>
    <item>
      <title>More adventures in building a first flow with Kestra.io</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Wed, 14 Jan 2026 14:26:47 +0000</pubDate>
      <link>https://dev.to/missamarakay/more-adventures-in-building-a-first-flow-with-kestraio-11ib</link>
      <guid>https://dev.to/missamarakay/more-adventures-in-building-a-first-flow-with-kestraio-11ib</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Oops, this accidentally turned into a blog series. You may want to read &lt;a href="https://dev.to/missamarakay/my-first-flow-with-kestraio-31g9"&gt;this blog&lt;/a&gt; first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;If you could see the revisions and comment blocks and all the other associated chaos that went into writing this blog... you would know I've been through it! But we are learning and iterating and I can nearly guarantee it will be way easier for &lt;em&gt;you&lt;/em&gt; when I'm done. Plus, I'm having a lot of fun.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's get into it.&lt;/p&gt;

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

&lt;p&gt;We left off on our adventure a bit stuck in the mud with the Google Calendar API + plugin. While nobody likes meetings, it was incorrectly returning an empty array with an otherwise successful looking API call. I fixed that!&lt;/p&gt;

&lt;p&gt;If you aren't into rants, scroll on down to "Now what?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Your &lt;code&gt;calendarID&lt;/code&gt; is probably not &lt;code&gt;primary&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I incorrectly thought that if I used the default &lt;code&gt;primary&lt;/code&gt; value I wouldn't need to change anything in my &lt;a href="https://go.kestra.io/as6xG6" rel="noopener noreferrer"&gt;Google Calendar Plugin&lt;/a&gt;. My personal and work emails don't have other calendars that I own. I have other calendars that have been shared with me and whatever special thing is going on with the "Birthdays" calendar, but I just assumed if I never made another calendar the first calendar ever made in my account would be &lt;code&gt;primary&lt;/code&gt; and that's incorrect.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;calendarID&lt;/code&gt; is often, but not always, your email address. Sometimes it will contain additional characters, and other times if it's part of a group, it may end in &lt;code&gt;@group.calendar.google.com&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;But by far the most irritating part of this was the practically silent failure. Those are the worst kinds of failures in software development and I spent DAYS revisiting this issue here and there to see if I could figure out what would work or not.&lt;/p&gt;

&lt;p&gt;But honestly, if you got this to work with &lt;code&gt;primary&lt;/code&gt; as your &lt;code&gt;calendarID&lt;/code&gt; let me know what are you doing to make it work. For now, we've &lt;a href="https://github.com/kestra-io/plugin-googleworkspace/pull/327" rel="noopener noreferrer"&gt;updated the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  You (probably) don't need to enable domain-wide authority to the service account
&lt;/h2&gt;

&lt;p&gt;I did stumble upon some guidance that said you needed to enable &lt;a href="https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority" rel="noopener noreferrer"&gt;domain-wide authority&lt;/a&gt; to the service account, which for this PoC and knowing my coworkers have run this plugin before, had me really skeptical. Maybe a reader can share more insight here, but I did &lt;strong&gt;not&lt;/strong&gt; need to enable this. Maybe &lt;code&gt;primary&lt;/code&gt; is a valid default if you have this enabled?&lt;/p&gt;

&lt;p&gt;So long as you've invited the service account to your calendar and you've correctly set up your API key, you are good. Just make sure your &lt;code&gt;calendarID&lt;/code&gt; is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now what?
&lt;/h2&gt;

&lt;p&gt;So I have the plugin working, but even with the service account it can only see busy blocks and a small amount of metadata. This has to do with how our Google Workspace is configured, so your experience might be different, just like mine is different on my personal account.&lt;/p&gt;

&lt;p&gt;I used this as an opportunity to learn the &lt;a href="https://go.kestra.io/0IWm4n" rel="noopener noreferrer"&gt;ForEach plugin&lt;/a&gt;, iterate through my meetings, and ultimately decide I probably wouldn't do anything beyond count the number of meetings I had. I do have access to the calendar link, but when the page loads it defaults to the current time slot, not the time slot for the actual meeting. Oh well. &lt;/p&gt;

&lt;h2&gt;
  
  
  ForEach
&lt;/h2&gt;

&lt;p&gt;I used the &lt;a href="https://go.kestra.io/0IWm4n" rel="noopener noreferrer"&gt;ForEach plugin&lt;/a&gt; (remember, everything is a plugin), mostly as an excuse to test it out. I'm iterating over the list of events I get back in the previous task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;for_each&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.flow.ForEach&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outputs.get_calendar_events['metadataList']&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
    &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get_individual_event&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.debug.Return&lt;/span&gt;
        &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;json(taskrun.value).htmlLink&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;set_meetings&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.kv.Set&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;meetings_today&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;taskrun.iteration&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1}}"&lt;/span&gt;
        &lt;span class="na"&gt;kvType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NUMBER&lt;/span&gt;
        &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PT5M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see I actually use the &lt;code&gt;metadataList&lt;/code&gt; because that's where the most interesting info I can "see" sits, but like I mentioned previously, the service account can really only see busy blocks. I did decide to keep the &lt;code&gt;htmlLink&lt;/code&gt; I pulled from the individual events because it was a good example of working with JSON. &lt;/p&gt;

&lt;h2&gt;
  
  
  KV Store
&lt;/h2&gt;

&lt;p&gt;Similarly to what I did with grabbing the &lt;code&gt;htmlLink&lt;/code&gt;, you can see I set a &lt;a href="https://go.kestra.io/wq8JTs" rel="noopener noreferrer"&gt;key value (KV)&lt;/a&gt; and use the &lt;code&gt;taskrun&lt;/code&gt; context somewhat trivially. It was really just an excuse to test these features in a flow.&lt;/p&gt;

&lt;p&gt;Now my flow sets a key-value pair and I can "see" it in the &lt;a href="https://go.kestra.io/IqWXh5" rel="noopener noreferrer"&gt;KV Store&lt;/a&gt;. Although I have to move fast because I only set it for 5 min (&lt;code&gt;ttl: PT5M&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;So while I'm not going to achieve my ultimate vision of "seeing" what meetings I was in, I will add the count to my recap notes because who doesn't like numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notion
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://go.kestra.io/6jAgh3" rel="noopener noreferrer"&gt;Notion plugin&lt;/a&gt; was interesting to investigate. The "OOTB" documented functionality was to delete all existing content on a page and add new fresh content. Not exactly what I was expecting. I was hoping for more of an "append to the bottom of the existing content" type experience. &lt;/p&gt;

&lt;p&gt;So I have some choices. I can create a feature request, I can create a new page for every weekly update, I can get the content off the page, put it somewhere, then put it back with the update (basically append it myself), or I could do some mix of the above.&lt;/p&gt;

&lt;p&gt;Since this is a PoC to really learn more about the product, I'll create a feature request and then take what I think will be the easiest route - create a new page for each weekly update. (&lt;em&gt;This is where she realized she needed to eventually adjust the trigger and meeting range to weekly.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;I could also just run it and see what happens.&lt;/p&gt;

&lt;p&gt;So you'll never guess what happened when I actually ran the Notion Update plugin - it appended the content to the bottom of the page. Just like I wanted!!! So scratch what I said about created a separate page for each update, but I'm back to making an issue anyway because I cannot read the page... the response didn't include the actual page content. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pivot again? Confluence?
&lt;/h2&gt;

&lt;p&gt;Because I can't read the content from my Notion page via the plugin, I'm exploring the &lt;a href="https://go.kestra.io/v1uXls" rel="noopener noreferrer"&gt;Confluence plugin&lt;/a&gt; which appears to do some of the same things Notion will do.&lt;/p&gt;

&lt;p&gt;The biggest problem I ran into was the Confluence API wants &lt;em&gt;you&lt;/em&gt; to pass back the version number, incremented &lt;em&gt;exactly&lt;/em&gt; 1 over the current one. I used a KV Store value of type &lt;code&gt;NUMBER&lt;/code&gt; for this, but I can't &lt;em&gt;see&lt;/em&gt; the current version and I'm incrementing this value based on successful executions. Realistically, Confluence users will probably also update or modify the page in the browser, which will increment the version number and make the API unhappy. So another feature request! &lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;Oh GitHub. I love a love hate relationship with your query experience. My goal will be to get issues and PRs I created or was assigned to during the week and closed.&lt;/p&gt;

&lt;p&gt;As a reminder, or maybe a heads up, GitHub considers everything an issue, which is why you'll see me call the issues endpoint, but I'll get both issues and PRs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get_issues&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.http.Request&lt;/span&gt;
    &lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.github.com/orgs/kestra-io/issues?filter=assigned&amp;amp;state=closed&amp;amp;since=2026-01-07T08:00:00.000-06:00"&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('CLASSIC_GITHUB')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/vnd.github+json&lt;/span&gt;
      &lt;span class="na"&gt;X-GitHub-Api-Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2022-11-28&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;log_github&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.log.Log&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outputs.get_issues.body&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;for_each_issue&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.flow.ForEach&lt;/span&gt;
  &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outputs.get_issues.body&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get_individual_issues&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.debug.Return&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;json(taskrun.value).url&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;set_issues&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.kv.Set&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;issues_today&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;taskrun.iteration&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;kvType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NUMBER&lt;/span&gt;
      &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PT5M&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;log_issue_count&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.log.Log&lt;/span&gt;
    &lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kv('issues_today')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please enjoy this WIP snippet of YAML using the &lt;a href="https://go.kestra.io/qZyRJT" rel="noopener noreferrer"&gt;HTTP Request plugin&lt;/a&gt;. You may be asking yourself, where is the &lt;a href="https://go.kestra.io/TQQ06y" rel="noopener noreferrer"&gt;GitHub plugin&lt;/a&gt;?! Unfortunately, it didn't work for me on 1.1.11 but resolved with an updated to 1.1.13. You'll also see me taking healthy advantage of the &lt;a href="https://go.kestra.io/sWMfis" rel="noopener noreferrer"&gt;Log plugin&lt;/a&gt; because I want to see what values I'm getting as I'm building out my flow. I'll take those out eventually. Or not, who knows.&lt;/p&gt;

&lt;p&gt;💡 Pro tip to use the HTTP Request plugin if you are having trouble with any of the plugins that are essentially API wrappers. &lt;/p&gt;

&lt;p&gt;Will I add the GitHub plugin back into my flow? Maybe? It returns a &lt;code&gt;.ion&lt;/code&gt; and there is a plugin that turns a &lt;code&gt;.ion&lt;/code&gt; into a JSON. So realistically I can get this into a shape I want to work with and I think the returned response will always be quite small. I like that this gives me more opportunities to explore plugins and expression syntax, so I'll add it to the TODO list.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I got a pointer from a coworker to use the &lt;a href="https://go.kestra.io/rPOWlH" rel="noopener noreferrer"&gt;Return plugin&lt;/a&gt;, which looks pretty interesting for doing some of the data massaging I want to do with my issue and meeting responses. I don't need everything in the response, in fact, I need about 2 things in both of them, so I'll play around with this a bit more. &lt;/p&gt;

&lt;p&gt;I did use the Return plugin in a snippet above, but you'll notice I just glossed over it. I definitely need to revisit this and share more info with you. Hold me to it!&lt;/p&gt;

&lt;p&gt;Dare I say it's coming together? I can see how many meetings I went to, how many "issues" (remember, this is PRs and issues) I was assigned and closed, and I have &lt;em&gt;something&lt;/em&gt; working with both Notion and Confluence, even if it's not perfect. &lt;/p&gt;

&lt;p&gt;Now it may seem biased, but as I create these bugs and feature requests, the Kestra team has been super responsive to triaging them. Of course, I'm their coworker 😈, but I also strongly believe they are passionate about making a great product experience, so the more feedback they hear, the better they can respond and make a great product... well, great!&lt;/p&gt;

&lt;p&gt;If all goes well, I'll wrap up this blog series with one more blog to give you tips and tricks about working with plugins in your own &lt;a href="https://go.kestra.io/k91sTC" rel="noopener noreferrer"&gt;Kestra&lt;/a&gt; flows. &lt;/p&gt;

&lt;p&gt;But for now, I think I have a few more issues to create. &lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>opensource</category>
      <category>gettingstarted</category>
    </item>
    <item>
      <title>My First Flow with Kestra.io</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Fri, 02 Jan 2026 19:28:35 +0000</pubDate>
      <link>https://dev.to/missamarakay/my-first-flow-with-kestraio-31g9</link>
      <guid>https://dev.to/missamarakay/my-first-flow-with-kestraio-31g9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This turned into a series. &lt;a href="https://dev.to/missamarakay/more-adventures-in-building-a-first-flow-with-kestraio-11ib"&gt;Read part 2 here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As I'm learning more about &lt;a href="https://go.kestra.io/k91sTC" rel="noopener noreferrer"&gt;Kestra.io&lt;/a&gt;, the community, and the possible use cases, I wanted to build a small PoC (proof of concept) that resonated with me and leveraged a fair amount of the platform aspects so I could get some hands on learning beyond the existing tutorials and examples (which are great! Give them a try!).&lt;/p&gt;

&lt;p&gt;After talking with a coworker, I loved his daily reminder to log off scheduled on his calendar. This kind of daily ritual is really great for wrapping up your day and leaving work at work. Or at least trying to. &lt;/p&gt;

&lt;p&gt;I told him I was going to 100% steal his idea.&lt;/p&gt;

&lt;p&gt;Let me walk you through what I'm doing and learning as I go. This won't be a tutorial, but you can see how I learn and explore a new platform, following along with links back to the docs if you want to learn even more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements of the PoC
&lt;/h2&gt;

&lt;p&gt;I wanted to make sure this PoC covered multiple aspects of the platform, even if it might be a little trivial at times. I wanted to see the dashboards populate with some data, use a few &lt;a href="https://go.kestra.io/3LbDFD" rel="noopener noreferrer"&gt;plugins&lt;/a&gt;, and start to see the difference between the OSS Edition you can access for free and the paid experience with the Kestra &lt;a href="https://go.kestra.io/efPFOh" rel="noopener noreferrer"&gt;Enterprise Edition&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I needed to interact with the following during my daily or weekly shutdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scheduler/chron - what? You think I would remember to do this daily?&lt;/li&gt;
&lt;li&gt;Slack - our main communication tool and where my weekly recap ultimately needed to land, but also where I'll get the reminder&lt;/li&gt;
&lt;li&gt;GitHub - no surprise here, where the bugs, feature requests, issues, and PRs live for the source code and docs&lt;/li&gt;
&lt;li&gt;Notion - Throw this recap into my "Weekly recaps" so it doesn't get lost on Slack&lt;/li&gt;
&lt;li&gt;Google Calendar - Read my calendar and remind me who I talked to today or this week&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these looked like plugins that should reasonably work well for my PoC. Excellent!&lt;/p&gt;

&lt;p&gt;For my first iteration, I won't make this too terribly smart and it will prompt and grab the same info everyday, just for that day. Maybe v2 will do something more comprehensive on Friday when I actually write my weekly recap.&lt;/p&gt;

&lt;p&gt;After a quick search through the &lt;a href="https://go.kestra.io/fW0AX8" rel="noopener noreferrer"&gt;Blueprints&lt;/a&gt;, I didn't find anything specific that I wanted to build off of, so I ended up starting from scratch. I usually recommend building from or extending tutorials and existing examples.&lt;/p&gt;

&lt;p&gt;I should also mention I'm building this flow with the flow code editor, directly editing the YAML. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's a plugin?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://go.kestra.io/3LbDFD" rel="noopener noreferrer"&gt;Plugins&lt;/a&gt; are the essential building blocks for tasks and triggers in your workflow in Kestra. This might be a subtle shift from some platforms where the plugins are extensions or integrations, which they are in Kestra too, but they also include core functionality. You'll probably end up using several plugins in your flow, and many more if you are doing something non-trivial.&lt;/p&gt;

&lt;p&gt;See if you can spot the plugins I use in the YAML snippets below. You'll see a mix of 3rd party integrations and core functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kestra UI
&lt;/h2&gt;

&lt;p&gt;Learning new tools always requires spending a little time mapping your existing knowledge to the UI and terms. &lt;/p&gt;

&lt;p&gt;One of the things that I really struggled with early on was the purple, primary action button in the top right corner of the UI changes depending on what screen I'm on. So it could be used to create a flow, execute a flow, create a user (in Kestra &lt;a href="https://go.kestra.io/efPFOh" rel="noopener noreferrer"&gt;Enterprise Edition&lt;/a&gt;), etc. &lt;/p&gt;

&lt;p&gt;Leave me a comment and let me know how you feel about this UI design choice. Is it intuitive for you? Do you want a more descriptive button name?&lt;/p&gt;

&lt;h2&gt;
  
  
  Triggers
&lt;/h2&gt;

&lt;p&gt;You probably want to do something when something happens, whether that's a moment in time or based on an event like a form being submitted or new data arriving. You need a &lt;a href="https://go.kestra.io/XWhPvc" rel="noopener noreferrer"&gt;trigger&lt;/a&gt; for that. For my PoC, I want this to run every weekday around 4pm, when I'm thinking about wrapping up for the day.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;triggers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;daily_shutdown&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.trigger.Schedule&lt;/span&gt;
    &lt;span class="c1"&gt;#UTC Austin @ 4pm (could add timezone), except weekends&lt;/span&gt;
    &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0 22 * * 1-5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like these at the top of the YAML because they show me exactly when this flow happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tasks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://go.kestra.io/epVpkj" rel="noopener noreferrer"&gt;Flows&lt;/a&gt; require at least one &lt;a href="https://go.kestra.io/hE2je5" rel="noopener noreferrer"&gt;task&lt;/a&gt;. You simply cannot save a flow without a task. This makes sense because why would you have a flow that does nothing. &lt;/p&gt;

&lt;p&gt;I'll have several tasks in my flow, but I want to make sure I see a reminder or prompt in Slack. That will look something like this with the &lt;a href="https://go.kestra.io/yUdbHp" rel="noopener noreferrer"&gt;Slack plugin&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_reminder_message_to_slack&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.notifications.slack.SlackIncomingWebhook&lt;/span&gt;
    &lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('SLACK_WEBHOOK')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"text": "Time to shutdown"&lt;/span&gt;
      &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll need to revisit this to add something more interesting to the payload (like info from other tasks), but sending a Slack message is as easy as getting the tokens and secrets configured.&lt;/p&gt;

&lt;p&gt;Eventually, it will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_meetings_to_slack&lt;/span&gt;
      &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.notifications.slack.SlackIncomingWebhook&lt;/span&gt;
      &lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('SLACK_WEBHOOK')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;"text": "Here are the meetings you went to today: {{ outputs.get_calendar_events.events }} "&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we'll talk more about outputs a bit later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;

&lt;p&gt;I ended up doing a lot of logging tasks between the tasks that used plugins, mostly to verify what was coming back in the response and if I wanted to do anything else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get_cal_list_log&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.log.Log&lt;/span&gt;
    &lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outputs.get_calendar_events&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm still having some trouble getting the Google Calendar plugin to send more than an empty array back, so for now I'm logging the whole object I get back to see if I get any clues. &lt;/p&gt;

&lt;h3&gt;
  
  
  Flowable tasks
&lt;/h3&gt;

&lt;p&gt;I threw in a &lt;a href="https://go.kestra.io/czIlIi" rel="noopener noreferrer"&gt;flowable task&lt;/a&gt; because depending on how you classify a meeting, I don't have meetings everyday. I do have a blocker for lunch everyday, which is technically a meeting...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;if&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.core.flow.If&lt;/span&gt;
    &lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outputs.get_calendar_events.events&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;[]&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
    &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_no_meetings_to_slack&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.notifications.slack.SlackIncomingWebhook&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('SLACK_WEBHOOK')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;"text": "Hooray! No meetings today."&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;else&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_meetings_to_slack&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.kestra.plugin.notifications.slack.SlackIncomingWebhook&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secret('SLACK_WEBHOOK')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;"text": "Here are the meetings you went to today: {{ outputs.get_calendar_events.events }} "&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;I really like the human readable way this, well, reads. If, then, else shows me what the condition is and what's going to happen for the two branches.&lt;/p&gt;

&lt;p&gt;I know some platforms allow you to define a default path for flows, but I didn't see that here, which I actually really like. Introducing a default path feels confusing when you should rely on the evaluation of the condition.&lt;/p&gt;

&lt;p&gt;As I mentioned above this is currently always getting  &lt;code&gt;[]&lt;/code&gt; back from the Google Calendar plugin, so apparently I never have meetings, but when it works I'll have that taken care of with this flowable task. &lt;/p&gt;

&lt;h2&gt;
  
  
  Outputs
&lt;/h2&gt;

&lt;p&gt;I added an &lt;a href="https://go.kestra.io/L78byv" rel="noopener noreferrer"&gt;output&lt;/a&gt; that was trivial because I was most likely going to send the summary of the work I did to Slack in the message payload and wasn't sure if there would be any difference if I did or didn't have an output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sent_bool&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BOOLEAN&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the execution outputs, I wanted to see something I added and where it would show up in the UI. Again, trivial, because in this iteration I don't anticipate this flow making data available for a subsequent flow.&lt;/p&gt;

&lt;p&gt;I did use outputs across the various tasks too, so I could use the data from one task in the following task. &lt;/p&gt;

&lt;h2&gt;
  
  
  Revisions
&lt;/h2&gt;

&lt;p&gt;Don't do what I did as a lazy developer and put my secrets right into my flow. They stay in your &lt;a href="https://go.kestra.io/QxmWNf" rel="noopener noreferrer"&gt;revision&lt;/a&gt; history. Plain text. Oops.&lt;/p&gt;

&lt;p&gt;Secret handling in the Enterprise Edition is too easy to not use, so don't put your secrets plain text in your flow. Keep your secrets secret. Then use an expression like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;secret('SLACK_WEBHOOK')&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Revisions become really powerful as you are making changes to your flow, particularly while you are building and testing because sometimes a change doesn't work like you want, and through revisions you can see exactly what changes were made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I'm at
&lt;/h2&gt;

&lt;p&gt;I love that I can export an image of my topology directly in Kestra.&lt;/p&gt;

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

&lt;p&gt;So for now I don't have a "working" increment that I'm happy with. While it is firing every day, I still need to dig into why Google Calendar thinks I have no meetings... when I definitely have meetings. I'm currently playing around with public/private event visibility to see if that changes anything. More on that next week I'm sure when I also add the Notion and GitHub plugins.&lt;/p&gt;

&lt;p&gt;Have you built something with Kestra? Link me to your repo in a comment below. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This turned into a series. &lt;a href="https://dev.to/missamarakay/more-adventures-in-building-a-first-flow-with-kestraio-11ib"&gt;Read part 2 here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>opensource</category>
      <category>gettingstarted</category>
    </item>
    <item>
      <title>Get started with me &amp; Kestra.io</title>
      <dc:creator>Amara Graham</dc:creator>
      <pubDate>Fri, 26 Dec 2025 17:55:00 +0000</pubDate>
      <link>https://dev.to/missamarakay/get-started-with-me-kestraio-b94</link>
      <guid>https://dev.to/missamarakay/get-started-with-me-kestraio-b94</guid>
      <description>&lt;p&gt;Guess who got a new job and is going to take you along the onboarding and learning journey? ME! 🤗&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsijyzudcn56ulacbnr65.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsijyzudcn56ulacbnr65.gif" alt="Schitt's Creek Moira saying " width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided to go back to the core of my DevRel roots and join &lt;a href="https://go.kestra.io/k91sTC" rel="noopener noreferrer"&gt;Kestra.io&lt;/a&gt; as a developer advocate to help expand into the US market. I'm pretty excited to get back to learning and doing in public, and of course seeing all your wonderful faces in person at events. I've really missed the direct connection to the developer community. It's good to be back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfn0h6lfpgbfi8vv6p36.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfn0h6lfpgbfi8vv6p36.gif" alt="Schitt's Creek Alexis flicking her hair on both sides" width="517" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Kestra is a declarative workflow orchestration platform that really leans into the everything-as-code construct, but also has a pretty good experience for the config only no-coders out there too. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvug7dd0k7lpojbvjn06.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvug7dd0k7lpojbvjn06.gif" alt="Hannah Montana twirls transforming into her rocker personality" width="245" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I enjoy walking the line between coding and no-coding experiences out of pure laziness, the editor experience really sold it for me. I can see the YAML (code), no-code (that immediately modifies the YAML), and an editable topology all in the same editing experience in side-by-side panels. The YAML is readable, and the diagram gives me a great visual of what I'm building, and I can edit wherever I want.&lt;/p&gt;

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

&lt;p&gt;This really lights up all the areas in my brain in ways other platforms just haven't done. Leaning too hard into no-code and config only experiences made me frustrated that I couldn't &lt;em&gt;just write code&lt;/em&gt;, while sometimes I'd love to have someone else wrap the values I need for my solution in the boilerplate necessary to &lt;em&gt;just make them work&lt;/em&gt;. Callback to the next Hannah Montana gif because I do, in fact, like the flexibility that comes with the best of both worlds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using and evaluating Kestra
&lt;/h2&gt;

&lt;p&gt;Kestra has two editions - OSS and Enterprise - although it's three if you count Cloud. For the purposes of this blog, Cloud is just a different administered experience, a different flavor of Enterprise if you will. If you are looking for an OSS project to contribute to in the new year, we got that too! But I digress. &lt;/p&gt;

&lt;p&gt;Kestra OSS will be great for single user use cases, but also more than enough for doing a general evaluation of the flow building experience. Kestra Enterprise does unlock some pretty cool enterprise-y features, but digging into building your first flow is where things will click. At least that's where they did for me.&lt;/p&gt;

&lt;p&gt;I recommend following the &lt;a href="https://go.kestra.io/4lV2Eh" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt; and spinning up Kestra OSS with Docker compose. Just make sure you have Docker setup and, unless you are old like me, you probably already know Docker compose ships with Docker. What a time to be alive! &lt;/p&gt;

&lt;p&gt;Pop this into your terminal, then head to &lt;code&gt;http://localhost:8080&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --pull=always --rm -it -p 8080:8080 --user=root -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp kestra/kestra:latest server local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to the note in the docs about whether you need a persistent database backend or not. For my first few flows and executions this wasn't necessary and, to be honest, I just left it running in the background because I wasn't doing anything else that was compute heavy or intensive. Your mileage may vary! &lt;/p&gt;

&lt;p&gt;I then recommend heading straight to the &lt;a href="https://go.kestra.io/fW0AX8" rel="noopener noreferrer"&gt;Blueprints&lt;/a&gt; after running a tutorial or two. Once you execute a few flows to get some data in your dashboards you can dig in to building your own flow with the tons of available community &lt;a href="https://go.kestra.io/3LbDFD" rel="noopener noreferrer"&gt;plugins&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm still working on a flow that prompts me to wrap up my day or week by pulling together what I did in different places so I can accurately summarize what I &lt;em&gt;actually&lt;/em&gt; did. Maybe remind me to do a blog on this later. Keen eyes may notice my WIP in the flow editor screenshot. 👀&lt;/p&gt;

&lt;h2&gt;
  
  
  But wait, what's an orchestrator even for?
&lt;/h2&gt;

&lt;p&gt;I have this hypothesis that "orchestration" doesn't resonate with everyone in tech. At least not yet.&lt;/p&gt;

&lt;p&gt;I think many of us have a general understanding that we have many disparate systems with data &lt;em&gt;everywhere&lt;/em&gt; and if we could just use all of that together, we could &lt;em&gt;maybe&lt;/em&gt; solve some really cool and interesting problems. That's where the orchestration piece comes in - getting these different systems to talk to each other to accomplish a unified goal or a task.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fre9ej70vxyglwpt0pkrz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fre9ej70vxyglwpt0pkrz.gif" alt="Mickey in Fantasia conducting flashes of light off screen" width="480" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The folks in DevOps seem to get it, along with the folks in AI, probably because they are already working with so many different pieces and pulling things together, whether it's 5 different platforms and projects to standup a cluster or merging datasets from several different sources to provide the best answer.&lt;/p&gt;

&lt;p&gt;I'm sure I'll have another blog on this topic in the future, but I'm interested to hear what your definition of an orchestrator or orchestration is, when you learned about it, and how you use it, or maybe even how you know when to use an orchestrator. Leave me a comment and let's talk!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gry09syzzige6xsncmn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gry09syzzige6xsncmn.gif" alt="Schitt's Creek Alexis booping the computer" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Join me as I dig in more and let me know what you are building. Like I said, it's good to be back. 💜&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>gettingstarted</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
