Blog · Concept
Internal vs. client-facing tasks: a vocabulary problem
Most agency PM problems can be traced to a missing distinction in the data model — internal work and client-facing work are different categories that most tools treat as the same. Here's why that matters and what the alternative looks like.
Most of the friction agencies feel running project management is downstream of a single missing distinction: there's no shared vocabulary for the difference between internal work and client-facing work.
It sounds pedantic. It isn't. The vocabulary problem produces a data-model problem, and the data-model problem produces the duplication tax that eats half your team's Friday afternoon. This is a short piece about the distinction itself — what it means, why it matters, and what changes when you build a tool around it.
The distinction
Internal work is anything that happens inside the agency about the engagement. The estimate. The architecture call. The team discussion about whether the scope is realistic. The "this client keeps moving the goalposts" message in the team Slack. The art director's candid feedback to the designer.
Client-facing work is anything that happens with the client about the engagement. The deliverable. The approval request. The client's feedback. The polite summary of what the team learned this week. The status update you sent on Friday.
Both kinds of work happen on the same project. Often on the same deliverable. The brand identity round has internal-only discussion about which direction to recommend AND client-facing comment threads on each presented option. They're the same engagement; they're different categories of communication.
The data-model problem
The default data model of every general-purpose project management tool — Notion, ClickUp, Asana, Trello, Monday — represents a project as a tree:
Workspace
├── Team
│ └── Project
│ └── Task
│ └── Comment
There's exactly one type of task. There's exactly one type of comment. There's no field that says "this task is internal" or "this comment is for the client." When you need to express that distinction — and you do, every day, at an agency — you have to express it through structure: separate projects, separate workspaces, separate boards, separate databases.
That's the source of the duplication tax. The model has no place to put the internal/client-facing distinction, so the distinction lives in the names of containers ("Acme — internal" and "Acme — client") and in everyone's head.
What changes when you add the field
Add one column to the data model:
Task
├── id
├── title
├── description
├── status
├── visibility ← internal | client
└── ...
Two things become structurally possible:
The same task can hold both kinds of conversation. Internal-flagged comments are for the team. Client-flagged comments are for the client. The task is the unit of work; visibility is the unit of audience. They compose.
The client surface is a query, not a separate place. The client portal is the same data the team's dashboard sees, with WHERE visibility = 'client' in the query. There's no separate database to maintain in sync. There's no separate task to keep updated. The client side of the conversation lives on the same row as the team side.
That's the whole insight. Everything else — per-client portals, approvals on deliverables, AI-drafted status reports, immutable audit logs — is what becomes possible once the foundation is right.
Why most tools don't do this
The honest answer: most PM tools were built for internal teams with one audience, and the visibility-flag pattern was overkill for that case. Linear, Jira, Asana, ClickUp, Notion — all designed for organizations where everyone in the workspace is on the same side of the conversation. The audience problem doesn't exist; the field isn't needed.
For agencies, the audience problem is the dominant problem, and the field is the dominant feature. The reason a general-purpose tool can't be retrofitted into an agency tool is that the foundation is wrong — every feature added on top assumes one audience. To get per-task visibility, you'd have to refactor down to the schema layer, which is exactly the kind of change a mature product can't make without breaking everything else.
Bringing the visibility flag in from day one is what we did when we built Workhouse. It's why we're not strictly "an Asana competitor" or "a Notion competitor" — we're built for a different problem.
What this means in practice
If you accept that internal vs. client-facing is a real distinction worth modeling, the rest of the agency PM stack follows:
- A client portal that doesn't leak. Same data as the team dashboard, filtered by visibility. No second tool to maintain. (Feature page.)
- Approvals on the deliverable. Native approvals work because the visibility flag knows what's safe to send. (Feature page.)
- Status reports from real activity. The tool knows what's client-visible this week and what's internal-only. The report writes itself. (Feature page.)
- An audit log that respects the boundary. Internal-only audit events stay internal. Client-visible activity surfaces in the activity feed. (Feature page.)
None of those features make sense without the visibility flag. With it, they fall out naturally.
The takeaway
If your agency is feeling friction with your PM tool — Friday status updates that take too long, near-misses where internal comments almost reached a client, two databases that drift, more time reconciling than working — the diagnosis is probably structural. You're using a tool with one notion of audience, and your business has two.
The fix is either to keep maintaining the workaround (which is fine, if expensive) or to use a tool where the distinction is baked in.
How we did it in Workhouse. Or if you're more interested in the comparison than the feature page, the agency PM guide walks through the full evaluation framework.
Written by
Corey, Zach & Nick
Founders, Conversion Factory
Workhouse is the project management tool for agencies that's built around this stuff.
Free during beta. Migration help included.