cd /news/artificial-intelligence/more-jev-in-there-there-smart-condit… · home › topics › artificial-intelligence › article
[ARTICLE · art-142545] src=freek.dev ↗ pub= topic=artificial-intelligence verified=true sentiment=↑ positive

★ More Jev in There There: smart conditions and AI assignment

Spatie's There There helpdesk app added two Jev-powered features: smart conditions that turn a plain-language workflow description into a Boolean classification question, and automatic ticket assignment that uses a Choice question to pick among selected team members or users. The smart condition joins the existing spam and auto-reply questions in the same inbound classification request, and its stored probability is read by the workflow rather than re-querying Jev; assignment only fires when Jev has a clear favorite, otherwise the action makes no change. Disabled members and anyone without access to the ticket's channel are filtered out before the assignment question is asked, and spam and automatic replies are skipped before either assignment action runs.

by read3 min views2 publishedSep 30, 2026

Recently I wrote about how we use Jev in There There to detect spam, bounces, and automatic replies. Jev reads an incoming email and answers questions we define up front. We keep the probabilities and decide in our own code what counts as a match. The cheap checks on mail headers still run first.

That post ended with a promise that we'd find more uses for Jev. Here are two we have since added to There There: smart conditions for workflows, and automatic assignment to a team or person.

Workflows already let you match a subject, sender, or message body against text. That works when the words are predictable. A customer asking for a refund can also write "I was charged twice", "Could you reverse this payment?", or something in another language. A list of keywords gets long quickly.

With a smart condition, you describe what should match. Here's one of the example workflows in our local app:

The condition says "The customer asks for a refund or to cancel a payment." When it matches, the workflow adds a "Refund request" tag. We turn the description into a Jev Boolean question:

public static function question(string $description): Boolean
{
    return new Boolean(
        "The incoming message matches this workflow description: {$description}",
        [
            'true' => 'The incoming message fits the description.',
            'false' => 'The incoming message does not fit the description.',
        ],
    );
}

This question joins the spam and auto-reply questions from the first post in the same inbound classification request. The answer is stored with the message, and the workflow reads its probability from there. It doesn't call Jev again when the workflow runs.

The editor also lets you try a sample email or an existing ticket and see the score before you enable the workflow. Here, a customer asking about a duplicate charge gets a strong match:

Only incoming email is checked. Jev gets the subject, sender, and message text, not the whole ticket history.

When a ticket comes in, we need to get it to the right person. At Spatie, one person might handle billing questions, while someone else is better placed to help with a browser issue or a design question. We know who can handle what. The hard part is translating every way a customer might describe a problem into fixed routing rules.

In a workflow, you select the people Jev may choose from and add a short description of what each handles. Here, Dries handles frontend issues, Jef takes billing questions, Jimi handles design, and Zuzana picks up general support:

We ask Jev a Choice question with the people selected in the workflow. It chooses from that list, with one extra option for when nobody fits:

$response = Classification::of($state)
    ->questions(['assignee' => new Choice(
        $instructions,
        [
            ...collect($options)
                ->map(fn (Team|User $assignee) => $candidates->descriptionFor($assignee))
                ->all(),
            'None of these' => 'None of the others clearly fits this ticket.',
        ],
    )])
    ->timeout(10)
    ->classify();

We only assign when Jev has a clear favorite. Sending a vague ticket to the wrong person creates an unnecessary hand-off, so when nobody clearly fits, the action makes no change. Another workflow can pick it up later.

Before asking Jev, we remove disabled members and anyone who can't access the ticket's channel. The same approach can assign a team, with its own list and descriptions. Team and person assignment are separate actions, so choosing a team doesn't restrict which people Jev can choose from. Spam and automatic replies are skipped before either assignment action runs.

These additions make our workflows a lot more flexible. We can describe what we're looking for in plain language and route matching tickets to the people best placed to help. The workflow still decides what happens next.

If you missed the first part, read how we detect spam and auto-replies with Jev. You can also read the workflow conditions and workflow actions docs, or try There There.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @spatie 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/more-jev-in-there-th…] indexed:0 read:3min 2026-09-30 · —