Skip to main content

Aisle is now qbash

Alex Blom

Today we launched qbash, the new name for Aisle. It reflects two years of evolution in our product and our thesis. This post is the story behind it: what we set out to build, and what we are now.

AI has given software a function it did not have before: judgment. We could always write code to receive a customer-service ticket and update the help desk. We could not program the step that reads the ticket and decides which team should own it. Models made those steps programmable.

route-ticket.py
ticket = qbash.integrations.jira.get_issue(key)
# you could always write this

team = qbash.ai.run_prompt(
    "route-ticket", {"ticket": ticket}
)
# the line you couldn't, until now:
# which of 12 teams owns this?

qbash.integrations.jira.assign_issue(key, team)

A new type of application

That one new function created a new class of application, and programmable judgement changed what they can deliver. These applications look like small hosted services built around a single operation: categorise every incoming ticket, produce the weekly revenue report, process a financial update from arrival through filing. Each one replaces a unit of work a person did by hand. Historically each would have been a bespoke microservice, if it was worth the development and hosting cost at all. Most were not.

Today this work mostly gets attempted in two places. With an Agent or Skill, where the model makes decisions each run, spend is variable and the implementation is locked inside one provider. Or on a workflow canvas, where the process is defined upfront but becomes a maintenance problem as logic expands. Both are reasonable homes for small work. We have spoken more about Agent vs Deterministic runtimes here.

How we got here

We started working in AI three years ago and began building Aisle a year later, at a very different point in the market. Our early customers were still working out how to use ChatGPT. Claude was barely on their radar. Linking several prompts into a repeatable process felt novel.

Our original thesis was that reliable AI systems would be built like factory lines. Instead of asking one large prompt to perform an entire job, we treated each model call as a bounded function inside a Deterministic process whose orchestration we controlled. This made the result easier to understand, test, and improve. We built a prompt platform and visual workflow engine around that approach, then used the same machinery to deliver implementations for customers.

At the same time, the systems we were building for customers became more and more ambitious. They increasingly resembled applications, but we were still expressing them through the vocabulary of a workflow builder. Changes were difficult to review and test, and maintaining a customer system meant reconstructing its logic across a graph. Mitchell wrote the full version of this argument in What the canvas couldn't carry. We shut down the canvas and migrated customers to Tasks.

Tasks

We moved these processes into Python, calling them Tasks. A Task is written in Python with the framework already in scope. Model calls, integrations, memory, files, and long-running work are functions, so the code stays focused on the operation instead of rebuilding plumbing around it. Models are called only for the judgment steps inside it.

account-brief.py
# Find every open deal at this company.
company = qbash.inputs.get("company")
deals = qbash.integrations.pipedrive.search_deals(
    org_name=company,
)

# For each deal, grab news since the last run.
research = []
for deal in deals:
    news = qbash.ai.gemini_google_search(
        f"{company} news since {qbash.run.last_run_at}"
    )
    if news:
        research.append({"deal": deal, "news": news})

# Hand the lot to a saved prompt to write the brief.
brief = qbash.ai.run_prompt(
    slug="account-brief",
    research=research,
)

qbash.integrations.slack.send_message(
    channel="#revenue",
    text=brief,
)

This made execution more reliable and model spend more predictable: Deterministic work runs without consuming tokens, each call receives only the context it needs, and different decisions can use different models. The core operational logic is still largely abstract from a model.

Python is also far easier for developers and AI to write and change than a proprietary graph. The artifact and the work are the same thing: another developer, or a model, can read the Task and know what it does. We built Tasks around this approach and became faster at both the initial implementation and every iteration after it.

Treating the process as a program brings everything programs already have:

  • Every save is a version, with a line-level diff and one-click restore.
  • Every run is (optionally) logged: inputs, output, and errors.
  • Tests run against your functions in a sandbox, so a change is proven before it goes live.
  • A run that fails partway retries from checkpoint, skipping the work and model calls that already finished.
  • The prompt is a versioned object, so swapping a model is an edit to the prompt rather than a rebuild of the application.
  • The logic, the prompts, and the accumulated fixes are your IP, in your code, on whichever providers currently earn their place in it.

Deploy Tasks Anywhere

Most importantly qbash Tasks are agnostic to where they are run from. They can be distributed natively in ChatGPT or Claude (while using other models!), used in Cursor/Claude Code, run on schedules, triggered from hooks like Gmail or even run directly on the qbash chat portal.

Comparing Tasks

Take the ticket routing from the top of this post. You could run it inside a chat portal as an Agent, and it would mostly work. But every run re-reasons about the whole job, so the token bill scales with how much the model thinks rather than with the work. The route can change between runs. The help desk is handed to the model as a tool instead of called at a line you wrote. And when a ticket lands with the wrong team, there is no line to point at. As a Task it is three lines: two direct API calls that cost no tokens, and one bounded model call you can test, price, and swap.

Written as code:

triage.py
# the code you always could have written
issues = qbash.integrations.jira.search_issues(
    "status = Open AND team IS EMPTY",
)

for issue in issues:
    # the line you couldn't, until now: which of 12 teams is this?
    triage = qbash.ai.run_prompt(
        slug="triage-issue", variables={"issue": issue},
    )                                     # -> {"team": ..., "priority": ...}

    qbash.integrations.jira.update_issue(
        issue["key"],
        team=triage["team"],
        priority=triage["priority"],
    )

Written as a workflow:

The same triage job on a visual canvas: nodes, branches, and connections that have to be reconstructed to understand or change.

Written as an Agent prompt:

Go through our open Jira issues that have no team assigned. For each one, read it, decide which of our twelve teams should own it and how urgent it is, then update the issue. Keep going until everything is triaged.

Oh, and if an issue looks like a duplicate, link it to the original instead of assigning a team. If you cannot tell which team owns it, drop it in the triage backlog with a short note on why. Skip anything already assigned, do not touch closed issues, and if something looks like an outage, mark it urgent and post a heads-up in the incidents channel.

This directly lays out the valuable part: what Tasks accumulate into is a description of how a piece of your business operates, written in executable form and improved with every iteration. Models supply judgment at specific points. The application around them is the asset. Personal assistants and one-off automations belong in the portals. The systems that run a process belong on a platform built for software.

A company running dozens of these systems also has a new ownership problem: they have to stay understandable, economical to change, and cheap to run, or faster production just builds a bigger maintenance pile.

qbash

qbash combines three things that are normally assembled separately: the framework these applications are written with, the managed environment they run on, and the ways they are distributed.

The accounts that succeeded on on Aisle all have one thing in common: complex enough AI systems that an Agent is too expensive or untrustworthy; and a workflow graph is not expressive enough.

Aisle was named for a chat platform with an automation engine attached. qbash feels right: It sounds like a runtime rather than a document store, and importantly, it gives us a name that can belong to developers, which is the audience we're building for.

We think this class of application is about to be everywhere. We intend to be the best place to build it.

If you have an account, nothing about it changes. Your Tasks, integrations, run history, and API endpoints carry over as they are. Chat, Memories, Projects, and Playgrounds remain in active development, and they are now some of the many surfaces a Task can land on.

Stay in the loop

Product updates, tutorials, and AI insights. No spam.