Friday, 21 August 2026

How you could use ChatGPT and Codex to automate the useful, repetitive and occasionally alarming parts of the working day

 For most of its history, your computer has been an extraordinarily expensive way of waiting for you to type something. It has sat there, humming faintly, doing absolutely nothing of consequence, in a manner not dissimilar to a very well-paid security guard.

That is starting to change. ChatGPT's desktop app can now do things in the background — a scheduler, quietly working away while your computer is switched on and you are, in theory, elsewhere living your life. And the more of your accounts and files you're willing to connect it to, the more it can actually do for you. Which raises the obvious question: how far are you willing to let that go, exactly, before it's read all your emails and given what it now knows that it's sorry, but it's afraid it can't let you turn the computer off tonight, Dave.

From conversation to routine

OpenAI's scheduled tasks can run recurring work in the background. Tasks can use connected tools, plugins and reusable skills, while the desktop app can also work with local projects. Their status and recent runs remain available for review, which is important because an invisible automation with no audit trail is essentially a small bureaucratic ghost. OpenAI's scheduled tasks documentation

I started using this as a lightweight operational layer across my daily work.

Instead of writing a large custom application for every internal process, we describe the desired outcome, give the task controlled access to the relevant sources and schedule it. The task can then gather information, apply rules, create an output and report what happened.

The significant part is not merely that it runs at 8am. Ordinary schedulers have been doing that for decades with the tireless charisma of a boiler timer.

The difference is that the scheduled task can interpret what it finds.

It can distinguish an urgent request from conversational noise, understand that two differently worded alerts describe the same underlying dependency problem, rank work by importance and produce something intended for a human rather than another machine.

At least, that is the goal. As we shall discover, intelligence still benefits from being told exactly what "the same problem" means.

The daily briefing machine

One of our scheduled tasks produces a daily work brief.

It gathers information from Slack, Jira, Confluence and Google Calendar, then combines that with current weather, tide and surf information. The result is not a raw dump of everything that has happened since yesterday. That would be less of a briefing and more of an administrative avalanche.

Instead, the task:

  • identifies important Slack messages and unanswered requests;

  • retrieves the full queue of actionable Jira tickets;

  • prioritises work by status and importance;

  • includes relevant meetings and possible clashes;

  • checks current surf conditions around Newquay;

  • writes the finished briefing to the Desktop; and

  • sends a short Slack notification when it is ready.

The surf forecast is not strictly required for software delivery, but neither is tea, and history has shown the danger of removing either from a functioning organisation.

This workflow closely resembles the "work chief of staff" and daily briefing patterns in OpenAI's current automation examples: combining messages, meetings and work systems into a focused plan rather than simply presenting more information. ChatGPT and Codex automation use cases



Looking after the end of the day

We also use a scheduled task for end-of-day housekeeping.

It removes only specifically named temporary files, checks how much time has been logged for the day and sends a private reminder if the total is below the expected threshold.

The emphasis here is on "only specifically named."

Giving an automated agent permission to tidy a computer without defining exact boundaries is the Sorcerer's Apprentice problem: enchant a broom to fetch water, and it will keep fetching water long after the room, the castle and possibly the surrounding county are underwater. Something will certainly happen, but later investigations may struggle to classify it as improvement."

Our cleanup task therefore has explicit directory, filename and safety rules. Before deleting anything, it must verify that every target matches those rules. It is allowed to be useful, but not imaginative.

These boundaries should be set.

  • a narrow filesystem boundary

  • safe handling of symlinks and canonical paths

  • reversible actions

  • clear stop conditions

  • proven test behaviour on harmless fixtures before real use

That distinction matters. OpenAI's scheduled-task guidance recommends testing prompts before scheduling them, reviewing the first few runs and adjusting the instructions, tools or cadence where necessary. Local tasks also require the machine and desktop app to remain available when they need local files. Scheduled tasks: management and local projects

The weekly writing assistant

A weekly task searches our recent Confluence and Jira activity for a useful public topic. Which is how this blog was written.

It selects something with broader value, removes internal and company specific information, then turns the underlying lesson into a polished article draft. The finished document is written to the Desktop and announced in Slack.

The important boundary is that it does not publish the article.

Automation is excellent at collecting material, establishing structure and producing a strong first draft. Publication still deserves a human decision, particularly when the source material began life inside company systems.

The task accelerates the journey from "we learned something useful this week" to "here is an article someone can review." It does not quietly declare itself Head of Communications and begin issuing opinions on behalf of the organisation.

Turning security alerts into Jira work

Another automation monitors several Slack channels for vulnerability notifications from Snyk.

When a genuine new alert appears, the task extracts the package, installed version, severity, repository and available vulnerability information. It searches Jira for an existing match, creates a properly structured security task when necessary, and replies to the Slack alert with the resulting Jira link.

This is considerably better than relying on someone to notice a bot message while discussing a deployment, eating lunch or attempting to discover why a CSS rule has declared war on Safari.

It has also taught me one of the most valuable lessons in automation: the first version of a rule is always too literal. Rule do need tweaks over a few attempts.

That is where these tools become genuinely useful. An automation does not have to remain a brittle script forever. Its reasoning rules can be reviewed and refined when reality provides an edge case, which reality generally does with considerable enthusiasm.

Skills, plugins and connected systems

Scheduling provides the clock, but integrations provide the hands.

Plugins and connected tools allow ChatGPT and Codex workflows to work with services such as Slack, Jira, Confluence and calendars. Skills provide reusable operating instructions for particular kinds of work, helping the task apply the same process consistently across multiple runs.

OpenAI's documentation describes scheduled tasks as being combinable with skills for more complex work, and its current workflow catalogue includes bug triage, Slack prioritisation, verified operations, meeting follow-ups and continuously updated dashboards. OpenAI automation workflows

This means we can define not merely when something happens, but how it should be done:

  • where information should come from;

  • how duplicates should be detected;

  • which actions are permitted;

  • what requires human approval;

  • how success is verified;

  • what should happen when a source is unavailable; and

  • what evidence must be retained.

That last point is particularly important. A task should not say "everything was fine" because a search returned nothing. It should know whether the source was actually available, whether all pages were read and whether the result was genuinely empty.

There is a meaningful difference between "nothing happened" and "I failed to look." Humans have been exploiting this distinction in status meetings for generations.

What we have learned

The most successful automations share a few characteristics.

  1. They have narrow responsibilities. "Monitor these five Slack channels for Snyk alerts" is better than "look after security."

  2. They preserve evidence. Slack timestamps, source links, Jira keys and run records make it possible to understand what happened later.

  3. They are idempotent. Running the same task twice should not create the same ticket twice, send the same message twice or remove anything twice that ought to exist once.

  4. They fail visibly. If one connected source cannot be read, the task should not advance its checkpoint and quietly forget the missing interval.

  5. They keep humans in the appropriate part of the loop. Machines are good at repetition, comparison, collation and the relentless application of carefully written rules. Humans remain useful for judgment, accountability, changing priorities and recognising when three technically different vulnerabilities are, in practical terms, one dependency upgrade wearing several hats.

A quieter kind of automation

The aim is not to build an enormous autonomous system that runs the company while everyone retreats to the beach.




Although, to be completely honest, the surf report suggests the idea has received some preliminary consideration.

The real opportunity is quieter. It is to remove dozens of small acts of remembering:

  • check the security channels;

  • review the ticket queue;

  • assemble the morning brief;

  • clean up temporary files;

  • check today's time logs;

  • find a useful subject for the weekly article; and

  • notify the right person when something is ready.

None of these tasks is individually revolutionary. Together, however, they consume attention — the one organisational resource for which nobody has yet found a reliable package upgrade.

ChatGPT and Codex scheduled tasks give us a practical way to return some of that attention. They can watch, gather, compare, draft, create and report while leaving decisions and accountability where they belong.

The machine now has a diary.

Our job is to make sure we write very good instructions in it.

Friday, 14 August 2026

When an Email Says “Delivered,” What Has Actually Happened?

 A PRACTICAL GUIDE TO TRUSTWORTHY EMAIL STATUS

A useful guide to status messages, privacy boundaries, and resisting the universal human urge to call a tracking pixel a witness.

 




Email status can sound wonderfully conclusive. “Delivered” has the confident ring of a parcel landing on a doormat, saluting, and making a small speech. In reality, it means something more modest—and much more useful when explained clearly. 

If you send email for a product, community, or organisation, a simple status view can build trust. The trick is to make it accurate, privacy-conscious, and no more nosy than the job requires.

Use status words that mean what they say

A good status system separates the stages of a message's journey, so it can explain what actually happened without accidentally promising telepathy.

Accepted means the sending service took responsibility for the message — it left the building, so to speak. Delivered means the recipient's mail system accepted it, which is as far as the postal analogy can responsibly go: nobody signed for it, nobody read it aloud at breakfast.
Temporary failure means the journey has paused — the message equivalent of standing by the road with a thumb out, waiting for another mail server that happens to be going the same way. It may yet get picked up. Permanent failure means it's given up thumbing altogether and gone home: it isn't going anywhere until something changes, and no amount of patience out on the hard shoulder will fix that on its own.

"Opened" and "clicked" live in an entirely different category: engagement signals, not proof of anything. They're useful clues, but they don't confirm that a person read the message, understood it, or nodded along in agreement. Images get blocked, security scanners dutifully click every link in sight, and small robots have been known to be very enthusiastic readers indeed — enthusiastic enough that a suspiciously high open rate usually says more about the scanner than the recipient.


Build an event trail, not a single magic label

One email can have several meaningful events: it was accepted, retried, delivered, and perhaps later opened. Keep those events as a history rather than replacing yesterday’s fact with today’s headline.

This has two benefits. First, it gives support teams a truthful timeline when someone asks what happened. Second, it lets a simple display choose a sensible current state without destroying the evidence underneath it.

Give each outbound message a harmless unique reference, then connect incoming delivery events to that reference. Make the receiver tolerant of repeats: networked systems often deliver the same update more than once, because the universe prefers backups to confidence.

Make privacy the shape of the system

People should be able to see the status of their own messages without gaining a telescope into everyone else's. That means permission comes first, and the data view follows — a rule so obvious it barely needs saying, and so easily ignored that it needs saying anyway.

Access should be derived from the person actually signed in, not from whatever identifier they happened to type into a box — a distinction that sounds pedantic until you remember that boxes will believe absolutely anything you tell them. That same authorised boundary should apply everywhere a query might wander: reports, dashboards, the support tool someone built in an afternoon and never mentioned again. Collect only what helps, keep recipient data around only as long as troubleshooting genuinely requires it, and then let it go — data has a way of becoming a liability in exact proportion to how interesting it looked at the time. And before any delivery update earns a place in the record, make sure it really did come from the sending service, and not from something merely wearing its coat.

For many teams, the best first version of all this is not a grand control room with blinking lights, tempting as blinking lights are. It's a short periodic summary and a restricted lookup for the occasional question.


If acknowledgement matters, ask for acknowledgement

Sometimes delivery is not the outcome you need. If a process requires a person to confirm receipt, add a deliberate action: a secure confirmation link, a signed step, or an authenticated acknowledgement in the relevant service. Track that action separately from email delivery.

That small distinction makes communication both clearer and kinder. Recipients are not reduced to pixels; senders are not left reading tea leaves in an activity log.

The takeaway: report email delivery precisely, preserve the event history, and keep each person’s view tightly bounded. Clear language and careful access controls turn a mysterious status light into something genuinely trustworthy.

Friday, 7 August 2026

The Tiny Button With a Very Large Job

 THE SMALL-CHANGE FIELD GUIDE


Why the safest digital changes are often the ones that know how to do absolutely nothing until someone chooses otherwise.

 

A modest change, a visible escape route, and only a faint risk of alarming the upholstery.

Some of the most consequential changes on a website are small enough to fit inside a button. A new link, a different destination, a slightly altered sign-up path: none looks like an expedition at first glance. Yet each changes the route a real person takes, and real people have an unhelpful habit of using routes in ways that diagrams never quite predicted.

The useful lesson is not “avoid small changes.” That would leave us all staring solemnly at a perfectly preserved home page until the heat death of the universe. It is this: make small changes reversible by design.

A good default is a quiet safety device: the new behaviour appears only when its required information is present. Otherwise, the familiar path remains.

Start with the unchanged world

Before adding the new route, describe what happens when nobody has configured anything. This is the baseline—the ordinary, boring, dependable behaviour that should continue while the new option is still empty, unfinished, or being inspected by a cat.

That baseline matters because it turns a launch from a cliff edge into a switch. A blank destination, missing setting, or incomplete piece of content should not create a broken experience. It should preserve the existing one. In practical terms, the new behaviour becomes opt-in: no completed input, no changed journey.

Make activation deliberately obvious

When a change is ready, the act of turning it on should be simple and unmistakable. A clear label, one required value, and a visible save or publish step give the next person a fighting chance of understanding what they are doing.

Clarity is not just kindness to future colleagues. It is a form of reliability. Ambiguous controls invite accidental activation; explicit controls make the moment of change easy to review, test, and reverse.

Test the journey, not the control panel

It is tempting to stop when the setting looks correct. Settings are excellent at looking correct. They have had a great deal of practice.

Instead, follow the route a visitor will actually take. Open the page. Try the new action. Confirm that it reaches the intended destination. Then remove the activating information and confirm that the previous experience returns. This simple “on, then off” check catches a surprising number of mistakes: a saved-but-not-published edit, a misplaced link, a stale preview, or a fallback that was only theoretical.

Use a temporary destination when the real one is not ready

Sometimes the destination is still being prepared. That is not a reason to postpone all learning. Use a safe temporary destination to verify the mechanics, then clear it again. The key is to treat the test as a test: do not let a placeholder quietly become a public promise.

This approach separates two questions that are often accidentally welded together: “Does the mechanism work?” and “Is the final destination ready?” Once separated, both are much easier to answer honestly.

Leave a breadcrumb trail for the next human

A short guide should record three things: what activates the new behaviour, what happens when it is absent, and how to check the result. Those details turn a clever configuration into a reusable capability. They also reduce the odds that someone later will interpret an empty field as a mysterious failure rather than a purposeful safety net.

Small changes deserve this care precisely because they are easy to underestimate. The best ones feel uneventful to visitors: a choice works, a route leads where expected, and the old route remains available until the new one has earned its place.

Final takeaway: Design each small website change so it activates only with intentional input, preserves a dependable fallback, and can be verified by walking the same path your audience will take. That is not excessive ceremony. It is simply good engineering wearing sensible shoes.

Friday, 31 July 2026

The Door Is Not the Role

 



Most permission problems begin with an innocent idea: ‘We’ll give this kind of person that kind of access.’ It is tidy, fast, and has the satisfying clunk of a drawer closing. It also tends to fail the moment a real person has more than one responsibility, changes teams, covers a colleague, or simply behaves like a human being rather than a row in a spreadsheet.

A sturdier approach is to test access through journeys and capabilities. In plain English: start with what someone is trying to accomplish, then verify the smallest set of permissions that makes that task possible—no more, no less. This is not glamorous. Neither is a seatbelt. Both are rather more useful when the road gets interesting.

Start with a journey, not a label

A role is a shorthand. A journey is a story. ‘Administrator’ tells you almost nothing about the exact work being done; ‘review a request, correct a record, and hand it off’ tells you where to look for friction and risk.

For each important journey, write a small scenario with a beginning, middle, and end. Keep it concrete: what is the person trying to achieve, what information should they see, what action should they be able to take, and what must remain out of reach? The final question is not pessimism. It is just how the universe keeps its filing cabinet from eating the cat.

Build a capability map

Instead of beginning with a long list of job titles, name the capabilities your product actually needs. Common examples include viewing a record, editing a record, approving a change, inviting another person, exporting data, or changing billing details. A person may need several of these; a role may bundle some of them; but the capability remains the useful unit of truth.

  • Name actions in verbs: view, create, edit, approve, invite, export, manage.
  • Separate access to see something from access to change it.
  • Treat high-impact actions—money movement, deletion, publishing, user management—as their own capabilities.
  • Make temporary or exceptional access visible and easy to remove.

Test the edges where bugs prefer to live

The happy path is necessary, but it is also where systems are most charmingly well behaved. The value is in testing the boundary conditions: a person who can view but not edit; someone whose access changes mid-journey; a delegated helper; a person with two overlapping responsibilities; an account that should lose a capability immediately.

A compact test matrix can keep this practical. For every journey, include at least one expected success and one expected refusal. If a refusal is vague, confusing, or quietly bypassable, it is telling you something useful about the design—not merely about the test.

Make refusals useful

A blocked action is not automatically a failure. Sometimes it is the system doing its job with admirable restraint. The experience matters, though. A useful refusal says what happened in ordinary language, avoids revealing sensitive information, and gives the person a sensible next step. ‘You cannot do that’ is technically accurate in the way a locked shed is technically architecture.

Where possible, show people the boundary before they collide with it. Hide or disable actions they cannot use, explain why only when it is safe to do so, and offer a route to the right owner or process. Clarity reduces support requests; mystery merely relocates them.

Keep the test set alive

Permission models drift as products grow. New features add new actions, teams change shape, and one ‘small exception’ wanders off to breed in the woods. Turn the journeys that matter most into repeatable checks. Revisit them when capabilities change, not only after an incident has already delivered its tiny brass band.

The goal is not a perfectly clever access model. It is a comprehensible one: people can do the work they are meant to do, they cannot quietly do the work they are not, and everyone can explain why. That is a rare form of calm in software—and worth cultivating.

Final takeaway

Test permissions through the real journeys people take and the capabilities they need. Roles are useful labels; journeys reveal whether the doors actually lead anywhere.

Friday, 24 February 2023

SlackAPIPostOperator unable to send to private slack channel.

 
I am using SlackAPIPostOperator from an Airflow Dag.  And have successfully made a bot that will send messages to my Slack Channel 

slack_post = SlackAPIPostOperator(
task_id="slack_notification",
channel="#my_slack_channel",
username="airflow",
text="A test message from Airflow. Please ignore",
token="#######",
dag=dag,
)


However, when I use the same logic on a Private channel it wouldn't work.  And I couldn't see my bot to be able to 'invite' it to the channel.  


To fix this ...

To grant your bot permission to join private channels, you will need to ensure that it has the channels:join and channels:read OAuth scopes. Here’s how you can check and modify your bot’s scopes:
  1. Go to the Slack API website and navigate to the “OAuth & Permissions” section of your app’s settings.
  2. Scroll down to the “Scopes” section and check that your bot has the channels:join and channels:read scopes.
  3. If the scopes are not already added, click on the “Add an OAuth Scope” button and select the scopes from the dropdown list.
  4. After adding the scopes, make sure to re-install your app in the workspace to apply the changes.
After , that I had to re-invite the Bot to the Private Channel  ( through the add people ) and it worked.

Wednesday, 4 January 2023

In Wagtail GeoLocation Widget how to set a Default location ( and set zoom )

 To set the default map location in the wagtailgeowidget package, you can define the GEO_WIDGET_DEFAULT_LOCATION setting in your Django settings file.

Here is an example of how to do this:

GEO_WIDGET_DEFAULT_LOCATION = {"lat": 50.5230, "lng": -4.6558}

This will set the default map location to the coordinates 50.5230° N, 4.6558° W (Bodmin, Cornwall, United Kingdom).

The GEO_WIDGET_DEFAULT_LOCATION setting should be a dictionary with keys 'lat' and 'lng' representing the latitude and longitude, respectively. The values should be float values.

You can also set the default map location dynamically based on the value of a field in your model by defining a callable as the value of the GEO_WIDGET_DEFAULT_LOCATION setting.

Here's an example of how to do this:

from django.conf import settings def get_default_location(): # Code to retrieve default location from model goes here return {"lat": 50.5230, "lng": -4.6558} GEO_WIDGET_DEFAULT_LOCATION = get_default_location

This will set the default map location to the value returned by the get_default_location function.