Business process automation services, built one process at a time

This page assumes you can name the process that is hurting, down to the specific task.

The rest is build detail, including one enquiry-to-CRM process written out in enough depth to rebuild and a table of what the system does when a dependency stops responding. Apefo Ltd trades as JNET.support; builds are delivered remotely from the UK.

Bring us the process you want built

Architecture

What a built automation looks like

  1. Trigger Rule based Signed webhook. Payload persisted before anything runs.
  2. Validate Rule based Honeypot, email syntax and MX, company inference, deduplication.
  3. AI assist AI assisted One call. Closed category list, two-sentence summary. Decides nothing else.
  4. Route Rule based Category-to-owner lookup with a documented fallback. Needs the category, so it runs after the model call.
  5. Write Rule based Contact, opportunity, one task with a named owner and a due time.
  6. Review Human review Owner confirms the category on the CRM card and checks the summary kept the constraints.
  7. Monitor Rule based Retries, alerts, and a queue depth someone actually looks at.
Failure queue

Any step that fails a check routes here instead of continuing. A named person clears it, and the item keeps its submission ID so it can be replayed once the cause is fixed.

  • Deterministic step Rule-based. Testable, repeatable, cheap.
  • Model-bounded step One call, constrained output, no authority to act.
  • Human review The record exists, but nobody acts on it until a person has confirmed the category.
  • Failure queue Anything that fails a check waits for a person. The only thing discarded without a record is a bot submission.

Which processes are worth automating

Automation earns its build cost through repetition and predictability. A process that runs often but changes shape every time is a worse candidate than one that runs less often in a fixed shape. This is the test applied before anything is quoted.

TestLine worth building againstWhy the line sits there
TestFrequency and total timeLine worth building againstWeekly, or 20+ runs a month, or rarer runs that each eat hoursWhy the line sits thereRare and quick does not repay build and maintenance. A monthly report that swallows a day still does
TestHandling timeLine worth building against4+ minutes of attention per run, or a wait longer than a working dayWhy the line sits thereSub-minute tasks are usually a UI problem
TestInput shapeLine worth building againstThe same 6-12 fields in a recognisable structure, 8 runs in 10Why the line sits thereBelow 8 in 10 you are building an exception handler with an automation attached
TestRule stabilityLine worth building againstDecision rules unchanged for six monthsWhy the line sits thereFaster-moving rules outrun any build
TestNamed ownerLine worth building againstOne person, by name, whose work gets easierWhy the line sits thereWithout a name, nobody notices when the output goes wrong
TestReversibilityLine worth building againstA bad output is correctable the same day without contacting a customerWhy the line sits thereThis decides how much sits behind a human confirmation
TestSystemsLine worth building againstEvery system has an API, a webhook, or a scheduled exportWhy the line sits thereDriving a desktop app through simulated clicks is a different, more fragile category

This is the build-scoping version of the screen published in full in the eight-factor article. Rule stability and API availability are build-time checks that sit outside the scored model, alongside the exception-rate and observability checks.

Four conditions take a process off the build list until something changes. No named owner, which stops the work outright instead of reshaping it. Rules that change every month, because the build will encode last month's rules and keep applying them long after they stop being true. A free-text email as the only input, with no consistent structure and no sender template you can influence. Runs four times a year, so the operator has forgotten it exists by the second run.

An error that cannot be undone is a different kind of problem. It is a design constraint, not a disqualifier. Irreversible steps get a person on the trigger, not on the review.

How the choice between rules and AI gets made

Most of this work is deterministic, and that is the correct engineering answer. A rule you can write down is testable, cheap per run, and behaves identically on the ten-thousandth execution. A model does none of those things. AI belongs in a narrow band: reading messy text, pulling fields from documents with no fixed layout, drafting a first version, compressing something long into something short.

StepBuilt asReason
StepRoute on a picklist valueBuilt asDeterministicReasonThe value is already a closed set
StepArithmetic: totals, VAT, due dates, ageingBuilt asDeterministicReasonModels are not calculators. Sums are computed in code, then shown to a model, never derived by one
StepDuplicate detectionBuilt asDeterministicReasonA hash of the normalised email and the opening of the message, inside a 24-hour window, is exact
StepField validation and required-field checksBuilt asDeterministicReasonThe schema is known in advance
StepClassify free text into a fixed category listBuilt asAI, closed list, confidence thresholdReasonThe input varies without limit, the output does not
StepExtract supplier, date, net and total from PDFs with dozens of layoutsBuilt asAI, then validated in codeReasonLayout varies. Values are range-checked and cross-footed afterwards
StepSummarise a long thread or ticket historyBuilt asAIReasonNo rule expresses this, and a person reads the result
StepDraft a first reply or documentBuilt asAIReasonFaster writing. A person still sends it
StepDecide a refund, discount, credit or hiring outcomeBuilt asNeitherReasonThe automation prepares the decision and a person makes it

In a fifteen-step build, expect the model to touch one or two of them. If a proposal has AI in every step, someone is selling model calls, not a working process.

Anatomy of one automated step

An enquiry arrives through the website form and has to become a CRM record with an owner and a task somebody is accountable for. Here it is in enough detail to rebuild.

Trigger and input

The form sends a signed POST to a webhook. The signature is verified first; unsigned or stale payloads are dropped and counted. The raw JSON is written to durable storage with a submission ID before processing, so if every downstream step fails the enquiry still exists somewhere retrievable.

Twelve fields: full_name, work_email, company, phone (optional), country, enquiry_text (free text, 2,000 characters), source_page, utm_source, utm_campaign, consent_marketing, submitted_at (server time, not browser time), and a hidden honeypot.

Validation, in order

Cheap rejections first, history last

Each check runs before the next, so nothing expensive runs on input that was never going to survive. What happens to a failure depends on which check caught it. Bot submissions are dropped, duplicates are annotated on the record that already exists, and anything genuinely ambiguous waits in a review queue with a named owner.

  1. Bot check

    Condition
    Hidden honeypot field is filled, or the form is submitted less than two seconds after page load.
    Action
    Discarded before any processing.
    Exception
    Counted for monitoring. No alert, no record, no notification.
  2. Email validation

    Condition
    work_email fails syntax parsing, or its domain has no MX record.
    Action
    Not created in the CRM.
    Exception
    Held in the review queue with the reason recorded, because a typo and a fake address look identical to a validator.
  3. Company inference

    Condition
    company is empty.
    Action
    Free-mail domain: queued. Corporate domain: the domain becomes a provisional company name.
    Exception
    Queued items carry the reason no identifiable organisation. Inferred names are flagged as inferred, never presented as confirmed.
  4. Deduplication

    Condition
    SHA-256 of the lowercased email plus the first 200 characters of enquiry_text matches a submission from the last 24 hours.
    Action
    A note is appended to the existing record.
    Exception
    No second record, no second task, no second notification. The duplicate is visible on the original.

The AI step, and its boundaries

Survivors get one model call. It receives enquiry_text and returns a two-sentence summary for whoever picks it up, plus a category from a closed list of five (new project, existing client support, recruitment, supplier pitch, unclear).

It does not choose the owner, set priority, judge value, write to the CRM, or reply to the sender. It cannot return a category outside the list; anything unparseable becomes unclear. The model is asked to return a confidence score alongside the category, and below a threshold the category is overwritten with unclear regardless of what came back. The threshold is set per build by running the classifier over a labelled sample of real enquiries and choosing the point where false confident answers stop; on our own intake that landed at 0.7, and it is not a number to copy without doing that exercise. The original text is stored verbatim in its own field, so the summary is never the only surviving version of what the person wrote.

Review and output

The owner gets a CRM card carrying the summary, the category, and the raw text underneath. They check two things: that the category is right, and that the summary has not dropped a hard constraint such as a deadline, a named system or a budget ceiling. Reassigning the category rewrites the task title and the owner, and the correction is logged with its original value, which is what tells you months later whether the classifier is drifting.

The output is a contact and an opportunity record with source = web form, category set, summary as the first note, raw text preserved, owner assigned from a category-to-person lookup with a documented fallback for absence. Then one task, titled Respond to {company} ({category}), due 17:00 the next working day, assigned to that owner personally rather than to a shared queue. Queued items produce a single 09:00 digest to one named person.

What happens when it breaks

Each response is decided at build time and written into the runbook, not improvised during an outage.

FailureWhat the system does
FailureCRM API returns 5xx or times outWhat the system doesPayload is already persisted. Retries at 1, 5 and 25 minutes with jitter. Still failing after the third, the item stays queued and an alert names the submission ID
FailureCRM API returns 401 or 403What the system doesNo retry. Credentials or scopes changed. Immediate alert, and that integration pauses so the queue does not drain into failures
FailureRequired field emptyWhat the system doesHeld in the review queue with the missing field named. Nothing is written partially, because a queued item gets opened and looked at, while a record that is only two-thirds filled just gets trusted
FailureSame enquiry arrives twiceWhat the system doesHash match inside 24 hours. Note appended to the existing record. No duplicate, no second task, no second notification
FailureClassifier returns low confidenceWhat the system doesCategory forced to unclear and routed to the daily digest. The record is still created; only the routing is withheld
FailureScanned image with no text layerWhat the system doesDetected before extraction by checking for extractable text. Not sent to the model, because guessing on a blank read is the worst outcome. Filed for manual keying
FailureSomeone renames a spreadsheet columnWhat the system doesThe job asserts the header row against the expected schema before reading a single data row. Mismatch stops the run and alerts. Silent column drift corrupting six months of data is the failure this exists to prevent
FailureModel API unavailable or rate-limitedWhat the system doesDeterministic steps continue. The record is created with category unclear and an empty summary. The process degrades rather than stopping

The pattern underneath: retry what time alone might fix, queue what a person has to decide, alert on anything that will not clear itself, and make sure a failed step never leaves behind something that looks finished.

Who owns it afterwards

Automations decay because the world around them moves. A vendor renames a field or retires an API version. Someone adds a question to the form and nobody tells whoever maintains the endpoint. The colleague who owned the recruitment category leaves and the lookup table still points at their mailbox. Volume triples and a theoretical rate limit becomes a daily one. An OAuth token expires on a schedule nobody wrote down.

Two roles have to exist by name before handover. Someone in your business who reads the output and would notice it was wrong. That is usually the person whose work the automation makes easier, which is why the named-owner test sits at the top of this page. And someone technical holding the credentials who can change the code, whether that is your team, us, or a mix.

Handover covers a runbook for each failure above, the alert destinations, a credential inventory with expiry dates, the schema assertions, and the category-to-owner lookup as an editable table rather than a value buried in code. How much involvement continues afterwards depends on who holds the credentials and how often the surrounding systems change. Anything running on a schedule also needs somewhere to run, with monitoring and backups; where a build needs infrastructure rather than an application account, that part sits with YNVAR, the hosting side of the same house.

Narrow pilots that tend to work

Small enough to prove in weeks, with output someone reads daily so problems surface fast.

  • Form to CRM to owned taskThe process above, and a sound place to start because the trigger is clean and a dropped enquiry is visible to management.
  • Support inbox triageMessages tagged into a fixed set of request types, with deterministic rules doing the routing and the model only reading text.
  • Recurring report assemblyThe same handful of exports pulled on a schedule, schemas asserted, joined, and turned into the pack a person then interprets. All arithmetic in code.
  • Document field extraction into a review sheet: supplier documents parsed into a spreadsheet with a confidence column, low-confidence rows sorted to the top for keying.
  • Threshold notificationsSomething crosses a defined line and the responsible person is told once, with the context needed to act.

Versions of several of these run inside our own systems, which is where the failure table above comes from. That is why the table can name particular behaviours at all.

Processes we turn down

  • Nobody can describe it

    We turn down processes nobody can describe. If two people in the same team explain the current steps differently, the disagreement is the actual work, and encoding one version of it makes that disagreement permanent and harder to see. Map it first. That is what a readiness assessment is for.

  • The model would decide, not prepare

    We turn down builds where the model would make the decision rather than prepare it: approving spend, setting a price, judging an application, deciding a refund. Those get assembled, summarised and queued automatically, then a person decides.

  • Simulated clicks are the only path

    We turn down anything whose only integration path is driving a desktop application through simulated clicks; it breaks on the next update and neither of us enjoys the aftermath. And we turn down work under pressure to ship into production before anyone has watched the output for a fortnight, because that is where automations quietly corrupt data for weeks before anybody notices.

Decision system

How the design gets chosen

Once a workflow passes the screen above, two things set its shape. How messy the input is decides whether a model is involved. How hard the outcome is to reverse decides where the person sits.

Reversibility of the outcome Shape of the input
Structured input, reversible outcome Deterministic, end to end

Field-mapped rules do the whole job. No model is involved, because there is nothing to interpret.

01
Messy input, reversible outcome A model reads, rules act

A model extracts and classifies the text. Deterministic steps do the writing, so a bad reading fails visibly.

02
Structured input, hard to reverse Deterministic, person commits

The preparation is automated. A named person confirms the step that cannot be taken back.

03
Messy input, hard to reverse A model drafts, a person decides

The draft saves the typing. The decision, and the accountability for it, stays with the person.

04

Workflow contrast

From scattered work to reviewable workflow

Before
  • Scattered requests
  • Manual copy-paste
  • Unclear owner
  • Repeated documents
  • No review trail
After
  • Single intake path
  • Structured handoff
  • Clear owner
  • Reusable workflow
  • Review point before sensitive output

FAQ

How long does one process take to build?

It depends on how many systems it crosses and whether they have usable APIs. A two-system build like form-to-CRM runs to a small number of weeks including a shadow period. Anything relying on a file export because a system has no API takes longer, and most of the extra time goes on that export's edge cases rather than the core logic.

Do we need to buy new software?

Rarely. Most of this sits on top of the CRM, forms, spreadsheets and inboxes you already run. Where a piece is genuinely missing, such as a queue, a scheduler or somewhere for the code to live, you hear about it during scoping and not as a surprise line in an invoice. The reason for it gets written down next to the alternative we rejected.

Can you automate something that only lives in one person's head?

Yes, but the first phase is getting it out of their head, which means sitting through several real runs, not one interview. Expect the written version and the actual version to differ. That gap is normal, and better found before the build than during it.

What happens if we change CRM in a year?

The deterministic logic, validation rules and classifier prompt survive. The connector and field mappings do not. Builds keep system-specific mapping in one place rather than scattered through the flow, which keeps migration a bounded job. It still costs money, and we will say so at the time.

How is it tested before going live?

It runs alongside the manual process on real inputs, without writing to production systems, for long enough to hit the odd cases. Outputs are compared with what the person actually did, and every disagreement is examined: each one is either a bug or a rule nobody had written down.

Which of our data ever reaches a model?

Only the fields a step genuinely needs. In the enquiry build above that is the free-text body and nothing else. The email address, the phone number and anything else you nominate never enter the call, because the classification does not need them and the exclusion is easier to enforce at the boundary than to promise afterwards. Build access itself is scoped the same way, to specific API scopes rather than admin credentials. What nobody should offer you on a page like this is a legal or compliance guarantee.

Next step

Start with the process, not the tool

Describe one task your team repeats and you get a straight view on whether it is worth changing.