Adobe Coworker usecase: Syncing a Document Authoring Spreadsheet to AJO Offers

Sync spreadsheet-managed offer data into Adobe Journey Optimizer with Adobe Coworker.

Adobe Coworker usecase

I wanted to manage Adobe Journey Optimizer (AJO) offers the same way I manage most operational workflows - in a spreadsheet. Edit a row, validate it, and have the corresponding offer in AJO Experience Decisioning created or updated automatically, with the resulting offer ID written back into the Document Authoring sheet.

No manual re-entry. No copy-pasting into the AJO UI. Just a spreadsheet-driven workflow that can be reviewed and safely rerun.

mermaid
flowchart LR
    DA[Document Authoring sheet]
    SKILL[Adobe Coworker skill]
    AJO_MCP[Official AJO MCP server]
    CUSTOM_MCP[Custom ajo-mcp-server]
    AJO[AJO Experience Decisioning]

    DA --> SKILL
    SKILL --> AJO_MCP
    SKILL --> CUSTOM_MCP
    CUSTOM_MCP --> AJO
    AJO --> CUSTOM_MCP
    CUSTOM_MCP --> SKILL
    SKILL --> DA

The read path was already there

Adobe's CX Enterprise Coworker made the "read the sheet and talk to AJO" part relatively straightforward. Coworker includes an AJO MCP server out of the box, which gives a conversational skill access to capabilities like listing sandboxes, reading campaigns, retrieving journey data, and working with channel and loyalty information.

That existing foundation meant I could connect Coworker to Document Authoring, read the spreadsheet, and query AJO without building any of that integration from scratch.

The missing piece: writing Experience Decisioning offers

The challenge appeared the moment I needed to write data back to AJO. The official MCP server covers campaigns, journeys, loyalty, and channels well - but it does not expose the Experience Decisioning offer operations this workflow depends on, at least at the time of writing.

There were no tools for creating, updating, approving, deleting, or attaching content to an offer. For a sheet-to-offer sync, those operations are the entire point.

Building a custom AJO MCP server

To fill that gap I built ajo-mcp-server, a small MCP server that exposes exactly the offer operations the standard integration was missing. I deployed it on Adobe App Builder - Adobe's serverless application platform - so there was no separate infrastructure to provision or maintain, and authentication and access was already included.

Once deployed, the custom server appeared to Coworker as just another MCP endpoint, sitting alongside the existing AJO and Document Authoring integrations. The official server handled read-oriented capabilities; the custom server handled offer writes. Together they covered the full workflow.

The sheet-to-offers skill

With the missing tools in place, I created a Coworker skill called sheet-to-offers-plan. It follows a deliberate plan-first workflow:

  1. Read the offers sheet from Document Authoring.
  2. Validate every row against the expected schema.
  3. Compare the spreadsheet state with the existing AJO offers.
  4. Generate a written synchronisation plan categorising each row as Create, Update, Delete, or Error.
  5. Stop and wait for explicit approval.
  6. Apply the approved changes to AJO.
  7. Write the resulting AJO offer IDs back into the sheet.

The skill never touches AJO until a person has reviewed and approved the plan.

Why the approval boundary matters

The synchronisation itself is not the most important part of this implementation - the approval boundary is. A spreadsheet-to-system integration that applies changes silently can be dangerous. A malformed row, an incorrect identifier, or an unexpected deletion could affect live decisioning content without anyone noticing.

The plan-first model makes the workflow auditable and reversible before anything is committed. That is the difference between a tool that can be trusted and a script that quietly makes destructive changes.

Making the sync idempotent

Writing the AJO offer ID back into the source sheet is a small detail with a significant effect. When the skill runs again it can use the stored ID to find the corresponding AJO offer and update it rather than creating a duplicate. The lifecycle is straightforward:

Sheet state
Sync behaviour
Row without an AJO offer ID
Create a new offer
Row with an existing AJO offer ID
Update the existing offer
Invalid row
Report an error and skip
Offer removed from the approved source set
Include it in the deletion plan

Storing the ID in the sheet gives each row a durable relationship with its AJO offer and makes repeated runs predictable.

Building without a centralised review process

The part of this project I found most interesting was not the custom MCP server itself - it was how quickly the entire workflow could be assembled. Coworker lets users register their own plugin marketplace and install plugins into a personal collection, which meant I could build a custom skill, deploy an MCP server, register the endpoint, connect the components, and test the workflow end to end without needing to start a platform project or wait for centralised approval.

I could prove the workflow was useful, safe, and worth sharing before deciding whether it deserved broader adoption. The same repository now also includes read-only AJO tools, read-only Adobe Experience Platform toolkits, and a starter plugin for developers who want to build their own Coworker integrations.

The broader pattern

The sheet-to-offers workflow is a practical example of something more general. Document Authoring works well as a familiar operational interface. Coworker orchestrates the workflow. MCP servers expose product capabilities. When an existing integration does not cover a required operation, a custom MCP server fills the gap. An explicit approval step prevents silent destructive changes. And writing system IDs back into the source document makes each run safe and repeatable.

None of those pieces is complicated on its own. Assembled together, they produce a workflow that is both auditable and practical enough to rely on.