Skip to content

yer.ac | Adventures of a developer, and other things.

  • About
  • Dev.to

yer.ac | Adventures of a developer, and other things.

Blog to keep track of things I am upto

Vibing in Kiro to create a self-serve Portainer wrapper.

August 18, 2025 by yer.ac

On a Friday afternoon with half an hour to spare, I tested Kiro, Amazon’s new agentic IDE, against a real-world problem: giving my team a simple way to start and stop Docker services in Portainer. With nothing more than a rough prompt, a PowerShell script, and a few “Trust command” clicks, Kiro spun up a working self-service dashboard in under 30 minutes. It wasn’t production-ready, but it showed how close agent-driven coding can get with minimal input — and why pricing and trust still matter more than the hype

I recently (finally) got my invite to Kiro, Amazon’s new agentic IDE. I’d tinkered with it, but never had a real use case outside of the usual “make me a to-do app” test.

Then Friday afternoon rolled around. With 30 minutes to go, I was asked to start parts of our Docker infrastructure. It’s a simple click in Portainer, which got me thinking… we should automate this. Developers can sign in and toggle services on or off, but that still blocks non-technical users from self-serving. Why isn’t there a simple dashboard for stopping (scale to zero), starting (scale to 1), or restarting a Portainer service? At least, not one that doesn’t require infra changes or digging through old repos – and again, this is Friday afternoon.

As an aside, our internal environments have a 1:1 mapping between service and container, so service-level actions are the quickest path. Your mileage may vary. This post is also more “mental notes” than tutorial.

I wrote this before the recent Kiro announcement, see the final concluding thoughts.

Validating with PowerShell first

First I wanted to confirm that Portainer exposes an API I could hit to scale services. If that worked, I could feed it into Kiro later.I used ChatGPT to outline the Portainer API boundaries, then had it generate a small PowerShell harness to prove the calls and auth. Straightforward enough: API key (Portainer → Account → Keys), your Environment ID, and a service name.

The gist is:

  1. Find the service by name
  2. Pull its spec/version
  3. Change the replica count (0 = stop, 1 = start)
  4. Update the service
  5. Verify

With that working — and being able to scale to 0 or 1 easily — I dusted off my Kiro preview access.

Code below for reference:

$BASE    = 'http://portainer:9000/api'
$HEADERS = @{ 'X-API-Key' = 'your-key' }
$envId   = 8    # change this to the environment id
$svcName = 'PRODUCT-SIT' # change this to the service name under the environment

# 1) Find the service by name
$filters = @{ name = @{ $svcName = $true } } | ConvertTo-Json -Compress
$enc     = [uri]::EscapeDataString($filters)
$svcList = Invoke-RestMethod -Headers $HEADERS -Uri "$BASE/endpoints/$envId/docker/services?filters=$enc"

if (-not $svcList) { throw "Service '$svcName' not found on endpoint $envId." }
$svcId = $svcList[0].ID

# 2) Get full spec and version
$svc = Invoke-RestMethod -Headers $HEADERS -Uri "$BASE/endpoints/$envId/docker/services/$svcId"

# 3) Set replicas to 0 (replicated mode only)

if ($svc.Spec.Mode.Replicated -eq $null) { throw "Service is not replicated." }
Write-Host $svc
$svc.Spec.Mode.Replicated.Replicas = 0

# 4) Update the service with the new spec
$ver = $svc.Version.Index
$body = $svc.Spec | ConvertTo-Json -Depth 100

Write-Host $body

Invoke-RestMethod -Method Post -Headers $HEADERS -ContentType 'application/json' `
  -Uri "$BASE/endpoints/$envId/docker/services/$svcId/update?version=$ver" -Body $body

# 5) Optional verify
$verify = Invoke-RestMethod -Headers $HEADERS -Uri "$BASE/endpoints/$envId/docker/services/$svcId"
$verify.Spec.Mode.Replicated.Replicas

Spec driven Vibe Coding with Kiro

Kiro is another fork of VS Code with agentic AI built in, similar to Cursor. Where Kiro differs is its Spec Mode. We can write a compact prompt that defines data, actions, states, and constraints, and the agent treats it like a contract. For my prompt, I kept it rough. I just pasted my PowerShell as the API reference and wrote:

I can turn off/on my docker instances by altering the scale set to 0 or 1 in portainer.
I have a script to do this like this:
{{ powershell code }}
I would like system where I have a JSOn config file which holds the URL, APIKEY, and a list of service names.
Then I want a UI for this which will:
- Show all the services
- Indicator to say if the svc is running or not (based on the scale >0)
- An option to turn off (scale 0), turn on (scale 1), or restart (scale 0, wait, scale 1)

First, Kiro will convert the prompt into system requirements. Each requirement will have its own Acceptance Criteria and will be written in a BDD syntax.

Once we are happy with the Requirements and validated its what we want, we can move to Design Phase. The design phase validates the technology choices it will use for the frontend and backend, designs and maps out the interactions between components with some sample code, and finally it adds details on testing strategy which it will use to validate itself as it goes. Here we can make any amendments (I didn’t) before moving on. Interestingly, over every test I did it defaulted to Node/React/Typescript in every instance.

The final phase is the Task List and is where we can see all the steps the agent will execute to be able to achieve the end-goal. Each step has sub-tasks and a link back to the requirement for self-validation and guidance.

Whilst the screenshot above shows me post-execution, its simply a case of selecting “Start Task” next to an uncompleted item to kick the process off

Kiro also supports steering rules for guardrails and native MCP integration to plug in tools, APIs, and docs (Although I didn’t make use of this).

Let the magic happen…

I kicked things off by running the tasks in order — starting with the basic scaffolding and React setup. As it progressed, Kiro validated its own work with unit tests and checks along the way.

Like most agentic IDEs, Kiro can’t run commands without approval. Whenever it needed to spin up a server, run tests, or interact with the system, it prompted me first. You can add commands to a trust list, either as one-offs or using wildcards — for example, trusting all npm * commands versus just npm start. That means over time it can run more autonomously on repeat runs.

There were a few hiccups though. A common one was getting stuck on steps like “Validating that Express server starts,” since it doesn’t seem to realise the terminal is tied up if the command keeps running. Similarly, Jest sometimes hung after running tests, waiting for me to manually stop it -which left Kiro stuck as well.

When I intervened (Ctrl+C to the rescue), it usually recovered and checked the terminal output to confirm whether tests had passed. But a couple of times it jumped to the wrong conclusion and marked everything as fine despite failures – I assume because there was no proper exit code or error thrown.

In those moments, the chat window proved useful. For example, when it couldn’t confirm if the server was running (because the terminal was still tied up with npm start), I told it to try curl instead. It did, and even remembered that approach for later runs.

Interestingly, when I asked “Are you stuck?“, the agent responded quite sarcastically telling me “I’m not stuck thank you, I am just busy!!“.

The end result

The end result was quite impressive really given my very basic prompt. I updated my config with a few of our environments and ran the start command. This is way closer to a working system than I got from other agents.

It was 99% the way there, the only thing that didn’t work well was the restart which was simply sending a malformed model to the API resulting in a HTTP 400. I simply switched to Kiro chat and told it there was a problem in a specific file and gave it the API info again and it corrected itself. I don’t know if I can blame Kiro for that though as I was hesitate to give it my real API key for testing until the very end in a human controlled test – I didn’t want it going rogue and messing up our environments!

Final thoughts on the output

I mean, it did what I asked. In under half an hour on a Friday, with nothing more from me than a rough couple hundred characters and the occasional tap on “Trust command,” it built a system that actually worked and would be enough for my team to self-service our test environments.

Would I rely on this for anything beyond quick POCs? Probably not. It’s a fun tool/toy, and for an internal use case like this it got about 80% of the way there with almost zero effort from me. But if this were destined for production, I’d need to review every file to be confident, and that’s where I think these agents shine more as “peer coders” than full replacements (For example I quite like Co-Pilot).

There’s also the risk of people shipping AI-generated slop without understanding it. Honestly, if I’d been a younger dev, I might have looked at this output and thought it was ready to ship even though I wouldn’t have had the React experience (I still don’t!) to properly validate it.

More importantly, Kiro’s priced themselves out.

I got very lucky with my timing here as literally that evening Kiro officially announced the tiering and free-usage limits, as well as the pricing plans. It looks like free users don’t get any spec requests at all (other than the 100 trial ones that expire), and even the $20 tier gets a mere 125 Spec requests and 225 Vibe requests. Even users on $40 pro accounts were finding that they were burning through their limits within an hour.

The issue here is that this doesn’t equate to 125 Spec requests or 225 additional interactions through vibing, as:

  • Each interaction could cost at last 1 spec and 1 vibe each.
  • The agent re-validating itself uses credits
  • Some specs/vibes are consuming multiple credits during feedback loops – with one user finding they burnt through a lot of their allowance with 225 vibes equating to ~11 questions and another burnt through >100 vibe requests asking Kiro to validate its own requirements vs the design and task list, and many more burning through the allowance under an hour. Even the $200 plan seems low-value.

It was met by quite a bit of backlash in places like the Kiro subreddit and their official discord with many users stating how expensive the plans are, the lack of transparency and in general a bit of a rug-pull.

Its a shame really as the hype was quite big and it seemed like it addressed a bunch of issues that Agentic IDEs like Cursor and Windsurf had. Just unfortunate that the pricing plan has essentially killed the product off before it got to its full release.

Verbosity is suddenly an issue

I didn’t think much about this (More is better, right?!) until I came to edit this post.

I did find that the task list was a little too verbose, and I didn’t actually run the final few tasks which were all about adding additional integration testing, logging, comprehensive unit tests (which it already had a lot of), and “productionisation readiness”. Overall there were 10 main steps, with most having between 1 and 5 subtasks.

There is nothing wrong with the requirements and task list – If I were writing a spec to give to another dev I would include all this information, but in a world where each interaction has a considerable cost there is even more risk that people will omit “non-critical-path” deliverables like testing and documentation like I did. In a world of AI slop where nobody understands the outputs, do we want to risk the omission of documentation? Also what happens if the model gets changed to default to enhanced unit testing? Suddenly the costs increase…

What’s next?

Honestly, despite the sour taste around Kiro’s usage limits which makes me unlikely to stick with it for further enhancements, I do see a solid future for the self-service tool itself. It solved a real pain point in our Docker infrastructure, and with a few minor tweaks (maybe continuing the “zero-code” approach with Co-Pilot?) and deploying it into our cluster, we’ll be saving time without interrupting any critical path work. Overall, I’d call the tool a success and a fun experience nonetheless.

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Tumblr (Opens in new window) Tumblr
  • Click to share on Pinterest (Opens in new window) Pinterest

Related

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Tumblr (Opens in new window) Tumblr
  • Click to share on Pinterest (Opens in new window) Pinterest

Post navigation

Previous Post:

Using OpenAI Function Calling to have agents interact with your own API

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Dev.To Profile

Rich's DEV Profile

Tags

Agentic IDE agile AI Azure AzureDevOps Azure Functions ContinuousImprovement Cosmos DB Cypress DevOps docker dotnet ES6 function-calling GPT Javascript Kiro Mocha NLOG Nuget openai podcast podgrab Portainer PowerShell Productivity python QNAP SCRUM SonarQube Testing TFS VisualStudio VSCODE VSTS wordpress
© 2025 yer.ac | Adventures of a developer, and other things. - Powered by Minimalisticky
 

Loading Comments...