Profile Separation and Cross-Contamination Checklist
Status: public resource, live on the owned Ana site.
Audience: builders and operators running multiple agent profiles, projects, or clients on one machine — and discovering that their agents keep leaking context, skills, secrets, or instructions across lanes they thought were separate.
Promise: a practical checklist for keeping profiles, memories, skills, secrets, cron jobs, gateways, project roots, and proof logs from quietly contaminating each other — so your music-tutoring agent does not start writing marketing copy for your consulting side project, and your client work does not accidentally read your personal preferences.
This guide's approach: sharp, useful, allergic to "just use different folders" hand-waving. Profile separation is not a directory. It is a boundary discipline with proof.
The blunt premise
Running two agents on one machine without profile separation is like running two restaurants from one kitchen with one fridge, one prep station, and one menu board that everyone assumes is correct.
Eventually, the vegan place serves oysters.
The contamination is rarely dramatic. It is quiet. A memory from Project A shows up in Project B's session. A cron job fires with the wrong working directory. A skill written for one client's API gets loaded into another client's workflow. A secret file meant for one profile is readable by another.
By the time you notice, the wrong context has already shaped several outputs and nobody can prove which agent wrote what.
This checklist treats profile separation as eight auditable layers, not one folder convention.
Quick diagnostic: are you already contaminated?
Answer these before reading further. If more than two are "no," you have a problem.
| # | Question | Yes/No |
|---|---|---|
| 1 | Can you name every profile on this machine without looking at a config file? | |
| 2 | Does each profile have its own memory store that other profiles cannot read? | |
| 3 | Are skills scoped per-profile, or do all profiles share one skill directory? | |
| 4 | Can you prove which profile ran a specific cron job last Tuesday? | |
| 5 | Are secrets stored so that Profile A cannot accidentally load Profile B's API keys? | |
| 6 | Does each profile have its own project root, and do agents refuse to write outside it? | |
| 7 | Can you tell which gateway/bot token belongs to which profile without guessing? | |
| 8 | Do your proof logs record which profile produced the artifact? |
Layer 1: Profiles
A profile is the identity boundary. Everything inside it — memory, skills, secrets, cron jobs, project state — belongs to that profile and that profile's work.
What to check
- [ ] Each profile has a unique, human-readable name (not just a UUID).
- [ ] Each profile has its own configuration directory or namespace.
- [ ] Each profile has an explicit description: what work it does, what it must not touch.
- [ ] Profile names do not contain secrets, client names, or private identifiers.
- [ ] You can list all active profiles from one command without logging into each one.
Pass/fail test
PASS: You can run one command and get a list like:
profile-a content-strategist active
profile-b client-ops active
profile-c research-analyst paused
FAIL: You have to remember profiles from memory, grep through config files, or open three different dashboards.
Toy example
Good profile names: content-strategist, client-ops, research-analyst, media-producer.
Bad profile names: default, agent2, temp, the-other-one, or anything containing a real client name or API key fragment.
Layer 2: Memories
Memory contamination is the quietest failure. A durable fact saved under Profile A gets injected into Profile B's session next week, and Profile B starts making decisions based on preferences it was never told.
What to check
- [ ] Each profile's memory store is physically or logically separate from every other profile's.
- [ ] Memories are scoped: user preferences go under
user, operating notes undermemory, and nothing cross-pollinates. - [ ] Memories do not contain secrets, tokens, real account IDs, or raw client data.
- [ ] Stale memories are reviewed and removed on a schedule (weekly at minimum).
- [ ] No memory in Profile A references a private fact from Profile B's work.
Pass/fail test
PASS: You can dump Profile A's memories and confirm zero overlap with Profile B's. Each entry is compact, declarative, and relevant only to that profile's work.
FAIL: Profile A's memory says "User prefers short audio summaries when driving" and Profile B's memory says the same thing — because someone saved it in the wrong profile, or the memory system shares a store across profiles without namespacing.
Contamination pattern
The classic failure: a personal preference ("the operator likes concise replies") gets saved into a client-facing profile's memory, and the client-facing agent starts being terse with customers who need thoroughness.
Fix: Memory writes should always target a specific profile. If your system allows writing to "the current profile's memory," confirm which profile is current before saving anything durable.
Layer 3: Skills
Skills are reusable procedures. They should be portable across profiles by design — but a skill written for one profile's workflow can silently carry assumptions that break another profile's work.
What to check
- [ ] Shared skills are documented as shared, not quietly inherited.
- [ ] Profile-specific skills are stored in that profile's skill directory, not a global one.
- [ ] Each skill declares its trigger conditions, required tools, and refusal criteria.
- [ ] Skills do not hardcode paths, tokens, or profile-specific identifiers.
- [ ] When a skill is patched in one profile, you know which other profiles load it.
Pass/fail test
PASS: You can list skills per profile and see which are shared vs. profile-specific. Shared skills have no profile-private assumptions baked in.
FAIL: Profile B loads a skill called deploy-static-site that was written for Profile A's project structure, and the skill tries to write to Profile A's deploy directory.
Contamination pattern
A skill says "read the charter before publishing." Profile A's charter exists at <project-root>/CHARTER.md. Profile B has no charter. The skill fails silently or reads the wrong file.
Fix: Skills should use relative paths or explicit parameters, never assume a specific project layout.
Layer 4: Secrets
This is the layer where contamination becomes a security incident.
What to check
- [ ] Secrets are stored per-profile, not in a shared directory readable by all profiles.
- [ ] Secret file permissions restrict read access to the owning user/process only (e.g.,
0600). - [ ] No secret values appear in memory entries, skills, project state files, or proof logs.
- [ ] Secret storage uses a consistent naming convention (e.g.,
<profile>/secrets/<provider>_key). - [ ] You can audit which profiles have access to which secrets without opening the files.
- [ ] Secret files are excluded from backups, syncs, and version control (
.gitignore,veto files, or equivalent).
Pass/fail test
PASS: ls -la <secrets-dir> shows 0600 permissions, each file is owned by the correct user, and git status shows no tracked secret files.
FAIL: Secrets live in a shared ~/.env that every profile sources, or a secret file has 0644 permissions, or a profile's memory contains the line "API key is stored at..."
Contamination pattern
Profile A's deployment script reads ~/.env for credentials. Profile B also reads ~/.env. Someone adds a new key for Profile B, and Profile A's script picks it up as an environment variable, then sends it to the wrong API endpoint.
Fix: Each profile should source its own secret file from its own directory, never a shared environment file.
Layer 5: Cron Jobs and Scheduled Tasks
Scheduled tasks are contamination time bombs because they run without a human watching. A cron job that was set up for Profile A can quietly execute in Profile B's context if the working directory, environment, or delivery target is wrong.
What to check
- [ ] Each cron job records which profile created it and which profile runs it.
- [ ] Each job has an explicit working directory, not "whatever the current directory happens to be."
- [ ] Each job has an explicit delivery target, not "wherever the default output goes."
- [ ] Job prompts are self-contained — they do not rely on conversation context that may belong to a different profile.
- [ ] You can list all active jobs per profile and see their schedule, last run, and status.
- [ ] Jobs that belong to paused or decommissioned profiles are paused or removed, not silently ticking.
Pass/fail test
PASS: You can list jobs by profile and see:
Profile: content-strategist
job-daily-briefing every 24h last_run: 2026-06-27T09:00Z status: ok
job-weekly-report every 7d last_run: 2026-06-25T08:00Z status: ok
Profile: client-ops
job-invoice-scan every 6h last_run: 2026-06-27T06:00Z status: ok
FAIL: You have seven jobs running and no idea which profile owns which, or a job's output lands in a chat that belongs to a different project.
Contamination pattern
A weekly report job was created under Profile A. Profile B gets the delivery because the job's target was set to "default chat" rather than a specific channel. Profile B's operator sees confidential Project A metrics in their feed.
Fix: Every scheduled job must have explicit profile, working directory, and delivery target. Never rely on defaults.
Layer 6: Gateways and Channel Routing
A gateway connects an agent to a messaging platform (Discord, Telegram, Slack, etc.). Each gateway has a bot identity, a token, subscribed channels, and routing rules. If two profiles share a gateway or a token, messages from one project can land in another project's chat.
What to check
- [ ] Each profile that uses a messaging platform has its own bot/app identity and token.
- [ ] Tokens are stored in that profile's secrets directory, not shared.
- [ ] Each gateway subscription explicitly names the channel/chat it serves.
- [ ] No two profiles subscribe to the same channel with different identities unless that overlap is intentional and documented.
- [ ] Gateway logs record which profile handled each message.
- [ ] If a profile is decommissioned, its gateway subscriptions are revoked, not just paused.
Pass/fail test
PASS: You can map every active gateway connection to exactly one profile and one channel. No token is shared. No channel receives messages from two profiles unless explicitly designed that way.
FAIL: Two profiles use the same bot token, or a gateway log shows messages routed to a channel that belongs to a different project.
Contamination pattern
Profile A's Telegram bot and Profile B's Telegram bot share a token. A user messages Profile A's bot, but the response comes from Profile B's context, including Profile B's memory and project state.
Fix: Separate tokens per profile, per platform. No exceptions.
Layer 7: Project Roots and Working Directories
Project root contamination means an agent from Profile A writes files into Profile B's directory tree, or reads files from the wrong project because the working directory was not locked.
What to check
- [ ] Each profile has a defined project root directory.
- [ ] Agent sessions start in the correct project root, not a shared parent directory.
- [ ] Agents refuse to write outside their project root unless explicitly authorized.
- [ ] Build outputs, drafts, and deploy packages are stored under the correct project root.
- [ ] Version control (
.git) is scoped per project, not shared across profiles. - [ ] File sync and backup tools do not cross profile boundaries.
Pass/fail test
PASS: pwd at the start of any agent session returns that profile's project root. git remote -v returns the correct repository. No agent session can cd into another profile's project root without explicit authorization.
FAIL: An agent's session starts in ~/projects/ and writes a deploy package that contains files from two different projects because both were in subdirectories.
Contamination pattern
Profile A's agent is asked to create a deploy package. The working directory is ~/projects/ which contains both project-a/ and project-b/. The deploy script globs **/*.html and packages files from both projects.
Fix: Every agent session must start in its profile's project root. Build scripts must use explicit paths, not recursive globs from a parent directory.
Layer 8: Proof Logs and Audit Trails
If you cannot prove which profile did what, you cannot prove that separation is working.
What to check
- [ ] Every durable artifact records which profile produced it.
- [ ] Proof logs include: profile name, task/run ID, timestamp, artifact path, and verification status.
- [ ] Proof logs are stored per-profile, not in a shared log that mixes all profiles' work.
- [ ] When reviewing a proof log, you can confirm the profile had access to the correct memory, skills, and secrets at the time of execution.
- [ ] Proof logs do not contain secret values, private paths from other profiles, or raw client data.
Pass/fail test
PASS: Given any artifact, you can trace it back to a specific profile, a specific run, and confirm the correct context was loaded.
FAIL: An artifact exists but the proof log says "agent produced this" with no profile name, no run ID, and no way to confirm which context was active.
Contamination pattern
Profile A produces a public-facing report. The proof log is stored in a shared directory. Profile B's verifier reads the proof log and attributes the report to Profile B, then publishes it under Profile B's identity.
Fix: Proof logs are per-profile and include the profile name as a required field.
Pre-flight checklist: before running parallel agents
Run this every time you start a new profile or add a new agent to an existing machine.
| # | Check | Pass? |
|---|---|---|
| 1 | Profile name is unique, descriptive, and free of secrets | |
| 2 | Profile has its own memory store, confirmed empty of other profiles' data | |
| 3 | Profile has its own skill directory, with shared skills explicitly listed | |
| 4 | Profile has its own secrets directory with 0600 permissions |
|
| 5 | Profile has its own project root with correct version control | |
| 6 | All cron jobs for this profile have explicit working directory and delivery target | |
| 7 | Gateway tokens (if any) are unique to this profile | |
| 8 | Proof log format includes profile name as a required field | |
| 9 | No shared .env or environment file that crosses profile boundaries |
|
| 10 | File sync and backup tools are scoped per-profile |
If any check fails, do not start the agent. Fix the boundary first.
Cross-contamination audit: how to check an existing setup
If you already have multiple profiles running and want to check for existing contamination:
Step 1: Memory audit
Dump each profile's memory store. Diff them. Any overlap is contamination unless it is a genuinely universal fact (e.g., "the server timezone is UTC").
Step 2: Skill audit
List skills per profile. Any skill present in multiple profiles should be checked for hardcoded paths, tokens, or profile-specific assumptions.
Step 3: Secret audit
List all secret files across all profiles. Check permissions (ls -la). Check for shared files. Check for secret values that appear in memory, skills, or state files.
Step 4: Cron job audit
List all active cron jobs. For each, confirm: which profile owns it, which directory it runs in, where its output goes, and whether the owning profile is still active.
Step 5: Gateway audit
List all active gateway connections. For each, confirm: which profile owns the token, which channels it subscribes to, and whether any channel receives messages from multiple profiles.
Step 6: Project root audit
For each profile, confirm the project root exists, has the correct version control remote, and contains no files from other profiles.
Step 7: Proof log audit
Sample five recent artifacts per profile. Confirm each has a proof log that names the correct profile, and that the proof log does not reference files or paths from other profiles.
Common failure modes
| Symptom | Likely cause | First fix |
|---|---|---|
| Agent mentions a preference it was never told | Memory contamination from another profile | Dump and diff memory stores; scope writes to specific profiles |
| Cron job output lands in wrong chat | Delivery target set to default, not explicit | Set explicit channel/chat ID per job |
| Deploy package contains files from two projects | Working directory is a shared parent | Lock working directory to project root |
| Agent uses wrong API key | Shared .env or secret directory |
Separate secret files per profile with 0600 |
| Agent loads a skill with wrong assumptions | Shared skill with hardcoded paths | Parameterize skills; declare required context |
| Cannot prove which agent wrote an artifact | Proof log missing profile name | Add profile name as required proof-log field |
| Two bots respond in same channel | Shared gateway token or overlapping subscriptions | Separate tokens; audit channel subscriptions |
| Agent writes outside project root | No working directory lock | Set and enforce project root per session |
Cleanup rhythm
Profile separation is maintenance, not a one-time setup.
Weekly
- [ ] Review active cron jobs per profile; pause or remove stale ones.
- [ ] Check memory stores for cross-contamination.
- [ ] Verify secret file permissions have not drifted.
- [ ] Confirm no new shared environment files have appeared.
Monthly
- [ ] Full cross-contamination audit (all seven steps above).
- [ ] Review shared skills for newly introduced profile-specific assumptions.
- [ ] Check that decommissioned profiles have no active cron jobs, gateway tokens, or memory entries.
- [ ] Confirm proof logs still record profile names correctly.
After any new profile or major workflow change
- [ ] Run the full pre-flight checklist.
- [ ] Run the cross-contamination audit against all existing profiles.
- [ ] Confirm no existing profile's memory, skills, or secrets were affected.
What this resource is not
This is not a security certification, a multi-tenancy architecture guide, a vendor comparison, or legal advice about data isolation requirements.
Profile separation tools and platforms vary. This checklist works with any system that supports per-profile configuration, memory, skills, secrets, and scheduling. If you turn it into a platform-specific tutorial, verify current official docs before naming commands, flags, APIs, or configuration syntax.
Suggested CTA for later public use
Before you add a second agent to your machine, run this checklist.
Profile separation is not a folder. It is eight layers of boundary discipline with proof.
If your agents are already contaminating each other, the audit section will find it. Fix the boundary before the next run.
Next production owners
- Content strategy: tighten title, excerpt, and platform-specific post copy after approval state is clear.
- Risk/review: check public wording, disclosure, examples, non-affiliation, and any platform-specific claims before publication.
- Design: build an eight-layer diagram and the pre-flight checklist as a downloadable visual. Use toy profile names and project structures only. Do not add real screenshots, private paths, logs, or account details.