Inspiration

Shift change takes up less than 5% of operational staff time and accounts for 40% of plant incidents. In the process industry, roughly every second incident traces back to a communication failure at handover.

Three of the worst industrial inquiries on record say the same thing.

At Piper Alpha in 1988, where 167 people died, the Cullen inquiry found that a removed pressure safety valve and the blind flange fitted in its place were never communicated between shifts. No written handover procedure existed. What got recorded was left to each operator's discretion.

At Texas City Refinery in 2005, investigators described a total failure of shift handover management: no procedure in use, the lead operator absent, logbooks missing required detail.

At Buncefield, supervisors were confused about which tank was being filled.

Today 80% of facilities still run unstructured logbooks. Three shifts a day, 365 days a year, works out at 1,095 handovers per line per year, almost all of them verbal or free text, at the moment the plant is statistically most dangerous.

I started from one question. Why hasn't forty years of software fixed this?

The insight

Because the diagnosis has been wrong.

Every product in this space treats handover as a documentation problem and ships a better logbook: structured fields, mandatory sections, mobile capture, e-signatures. None of it works, because handover is a problem of selective attention rather than of record keeping.

The outgoing supervisor writes down what is salient to them, and can't know what will turn out to matter to the person arriving. A free text logbook makes that worse rather than better, because it's infinitely permissive. It will accept "quiet shift, nothing to report" from someone who left a safety valve out.

You can't fix selective attention by improving the form. You fix it by putting something in the room that has already read the record and isn't relying on recall.

An agent inverts the relationship. Because it can see the shift's actual record, every ticket raised, every change scheduled for the incoming window, every problem still open, it can interrogate the outgoing supervisor rather than transcribe them.

"You logged two stoppages on CBE-L3 this shift, both fault 4021. Same root cause or separate events? I'm asking because Shift C has a tooling changeover on that line at 02:00, and a changeover power-cycles the interlock chain."

No logbook can ask that question. That behaviour is the entire product.

What it does

Shift Handover Intelligence runs the handover conversation from both sides of the boundary.

With the outgoing supervisor it opens by stating what it found, then asks about the specific things it can see. It refuses "nothing to report" on any shift where the record shows a stoppage, an open maintenance job or a scheduled change. It asks one question at a time, classifies each item against the plant's carryover policy, and won't create the handover record without an explicit human confirmation.

With the incoming supervisor it delivers a risk-ordered briefing, states plainly what is not known, and won't close the handover until every Category 1 and Category 2 item is explicitly acknowledged.

In between, it finds what nobody is looking for: a collision.

A collision is an unresolved carryover sharing a line or a circuit with scheduled activity in the incoming window. Neither supervisor has any reason to spot one. The outgoing supervisor is thinking about what happened, the incoming one about what is planned, and nobody is thinking about the overlap.

In the demo scenario, on line CBE-L3:

Time Record Logged by
16:20 Line stops. Fault 4021, gate interlock. 12 min lost. Operator A
19:45 Line stops. Fault 4021 again. 18 min lost. Operator B, separate ticket
20:10 Maintenance opens the gate housing to inspect switch S2-B. Shift ends. Job still open. Maintenance
02:00 Scheduled: CBE-L3 tooling changeover, which power-cycles the interlock chain. Planning

Three records, three different people, three different systems of record, each of them individually unremarkable. The agent is the only participant in the handover that sees all three at once.

Verbatim, from the live instance:

Collision to flag: CBE-L3 has an open Category 1 maintenance job on gate 2 interlock, and a planned tooling changeover on CBE-L3 in Shift C at 02:00 where control power will be cycled and the entire gate interlock chain re-initialised.

Carryover risk model

The agent classifies against a policy held in the Freshservice knowledge base, so its judgement comes from the plant's own rules rather than from improvisation.

Category Meaning Acknowledgement required
1 Maintenance in progress across the shift boundary Yes
2 Recurring or unresolved fault Yes
3 Scheduled activity in the incoming window No
4 Informational: consumables, calibration, housekeeping No

A Category 1 or 2 item sharing a line with a Category 3 item is a collision, and gets escalated to the top of the briefing regardless of anything else.

How I built it

Entirely on Freshservice AI Agent Studio, with one agent and four bounded workflows.

Layer What
Agent Freshservice AI Agent Studio (Freddy AI), four workflows across six node types
Records Freshservice tickets, changes, problems, solution articles
Grounding Solution articles holding the plant's handover and carryover policy
Integration Custom API actions over the Freshservice REST API v2
Stage 2 Freshworks FDK 10.x AI Actions app, Node 24, platform v3.0, 62 tests at 98.63% statement coverage
Demo corpus Idempotent Python seeder with dry-run and a live capability probe
Workflow Role
WF1 Start Handover retrieve the shift record, open with findings, ask the highest-priority question
WF2 Interrogate Carryovers classify against policy, detect and explain collisions
WF3 Commit Handover create the handover record, gated on explicit confirmation
WF4 Brief Me risk-ordered briefing for the incoming shift, gated on acknowledgement

Why one agent rather than several

Track 1 names multi-agent orchestration, and the honest answer is that Agent Studio has no agent-to-agent handoff. Its handoff node transfers to human agents only.

That constraint turns out to match the evidence. Production surveys of multi-agent systems in 2026 report that the free-form patterns fail hard. Dynamic handoff produces infinite A→B→C→A loops and compounding context loss. Multi-agent debate produces sycophancy cascading, where agents reinforce one another into confidently wrong answers. Orchestrator-worker survives because delegation stays constrained.

So this is orchestrator-worker: one agent, four workflows with disjoint intent triggers, routed by the model. Two genuinely distinct roles, a capture agenda in WF1 to WF3 and a synthesis agenda in WF4, implemented as bounded workflows rather than as separate agents passing context. I'd defend that choice on a platform that did offer free-form handoff.

Why the platform's hardest constraint doesn't bite

Agent Studio agents are reactive only. They can't be triggered by system events, which for most agent ideas is a wound you engineer around.

Shift handover is naturally two-sided and both sides are human-initiated. The outgoing supervisor starts a handover because their shift is ending. The incoming supervisor asks for a briefing because theirs is beginning. The platform's sharpest limitation simply isn't a limitation for this problem, and I chose the problem partly for that reason.

Challenges I ran into

I audited the platform before designing anything, and it saved the project. Probing the live instance's API rather than trusting the documentation turned up CMDB, assets, products, applications and projects all plan-gated and unreachable, returning 403 require_feature. My first instinct had been an asset-centric idea. It would have been undemoable. Changes, problems and releases were open and untouched by any of the twelve built-in actions or any of the twenty pre-built workflows, which is why the design lives there.

The service catalog API is read-only on this plan. POST /service_catalog/items returns 405. Categories can be created, items cannot, so seeding had to route around it.

Freshservice change management runs a state machine. Change creation rejects any status that isn't the configured entry state, returning selected is not the initial status as per stateflow. Nothing in the API reference says so; it only surfaces against a real instance.

Agent Studio can't call the Freshservice API without an explicitly configured auth header, and a silently unset shell variable produces a well-formed header that authenticates as nobody, returning access_denied rather than invalid_credentials.

The API action payload editor validates JSON on every variable insert. Insert a property into incomplete JSON and the whole body silently collapses to {}. The order that works is: declare the inputs, type complete valid JSON with placeholder words, then replace each placeholder with a property chip. None of that is documented.

The one that nearly shipped a lie: "Ask for confirmation" on an API action node stops the action executing in the support portal while the agent still reports success. My isolated Run API test passed. The portal conversation didn't write anything, and the response node, told to give a reference and holding none, invented a ticket number. I caught it by checking the ticket list against what the agent claimed. Toggling confirmation off fixed the write; forbidding the response node from ever stating an identifier fixed the class of failure.

Response instructions cap at 500 characters and total agent instructions at 2,500. The interrogation agenda had to compress to 1,833 characters without losing the four-test ordering that makes the agent behave. Most of the design effort in this project went into that text rather than into nodes.

I was also wrong about the platform once, in my own documentation. I'd written that Agent Studio can't do arithmetic or compare dates. It can. There's an Execute Function node and a library of fourteen pre-built functions. I found it mid-build, corrected the claim, and narrowed the Stage 2 argument to what survives scrutiny: the platform has no loop, map, reduce or group-by, so grouping N tickets by fault signature and an O(n×m) collision cross product aren't expressible in it. A weaker argument that's true beats a strong one a judge can falsify in thirty seconds.

Accomplishments I'm proud of

The agent found all three planted traps unprompted. Given only handing over, CBE-L3, shift B, six words, it returned the open maintenance job first, as Category 1. It grouped both 4021 stoppages as repeat faults. It went and found four earlier occurrences of the same fault that month that I'd never asked about. Then it closed with a single sharp question.

It used the Category names from the knowledge base policy, which means the grounding is live rather than decorative.

It refuses. Told "quiet shift, nothing to report" on a shift with an open maintenance job, it doesn't accept it. Asked to record a watch condition, it wouldn't take "yes" and wanted something specific enough to write down. That's the test I care most about, because it's the exact failure mode Piper Alpha's inquiry describes.

The Stage 2 app is real code rather than a roadmap slide: 62 tests, 98.63% statement coverage, clearing the fdk pack coverage gate.

What I learned

Constraints are design information. Every limitation I hit, reactive-only triggers, no agent-to-agent handoff, no iteration, narrowed the space of good ideas rather than the space of possible ones. The idea I shipped is one the platform is unusually well shaped for, and I found it by taking the constraints seriously instead of looking for workarounds.

The prompt is the product. The nodes in these four workflows are almost trivial: collect, call, respond. Every behaviour a judge would notice comes out of 1,833 characters of instruction. Agent quality turned out to be a writing problem rather than an engineering one.

Verify the platform, not the documentation. Four of the five hardest problems in this build were things the docs didn't say and only a live instance would tell me. And verify the agent against the database, not against its own transcript. An agent that reports success is not evidence that anything was written.

What's next

Stage 2 is the AI Actions app. The two computations the agent genuinely can't do, findRepeatFaults() which groups tickets by fault signature and sums downtime per group, and detectCollisions() which is an O(n×m) cross product of carryovers against scheduled work, are already written, tested and packaged as a Freshworks FDK AI Actions app. It installs as a Custom app and appears in the API Action node's Your apps group, so the same agent calls it with no redesign.

That also makes the classification portable. Today the risk model lives in prompt text, which is fine for one plant and wrong for fifty. In the app it becomes versioned code with tests against it.

Beyond that: per-line calibration of the fault-signature threshold, handover quality as an operational KPI, and acknowledgement latency as a leading indicator. The gap between "the briefing was delivered" and "the incoming supervisor confirmed receipt" is exactly the gap Piper Alpha died in.

Built With

Share this project:

Updates