Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/virsanghavi/axis/llms.txt

Use this file to discover all available pages before exploring further.

guarded_write is the safest way to persist file changes in a multi-agent environment. It combines the tamper check of verify_file_lock and the file write into a single atomic operation — eliminating the race window that exists when an agent checks separately and then writes. The server only writes if two conditions are both true: you hold the lock on the file, and the file’s content matches the fingerprint recorded when the lock was granted.
guarded_write is available on the local stdio server only. The hosted MCP server at useaxis.dev/api/mcp does not have filesystem access. Hosted callers get tamper detection via verify_file_lock and write through their own editor.

Parameters

agentId
string
required
The agent performing the write. Must match the agent that holds the lock on filePath. If the lock belongs to a different agent, the call returns DENIED.
filePath
string
required
Path to the locked file to write, relative to the repo root or absolute. Must be a file (not a directory) inside the project root.
content
string
required
Full file content to write. guarded_write writes the complete file — it is not a patch or a diff operation.
projectName
string
The Axis project scope. Defaults to the auto-detected project name.

Return values

StatusMeaning
WRITTENFile written successfully. The lock’s content hash is refreshed to reflect the new content. Response also includes filePath and bytes written.
NO_LOCKNo active lock exists for this file under any agent. Call propose_file_access first.
DENIEDA lock exists on this file but it belongs to a different agent. You are not authorized to write it.
CONFLICTYou hold the lock, but the file’s current content no longer matches the hash recorded at lock-grant time. Another process wrote the file under your advisory lock. Re-read and reconcile before retrying.

How it works

1

Lock ownership check

guarded_write looks up the lock for filePath and confirms agentId is the recorded holder. Returns NO_LOCK or DENIED immediately if not.
2

Content fingerprint comparison

The file on disk is hashed and compared to the contentHash stored when propose_file_access was called. If the hashes differ, CONFLICT is returned — no write occurs.
3

Atomic write

If both checks pass, the server writes the file. When AXIS_ENFORCE_LOCKS=1 is set, the file was chmod’d read-only at lock-grant time; guarded_write briefly restores write permissions, performs the write, then re-applies read-only mode.
4

Fingerprint refresh

The lock record’s contentHash is updated to reflect the content just written, so any subsequent verify_file_lock or guarded_write call compares against the latest version.

Why prefer guarded_write over verify-then-write

The manual alternative is:
verify_file_lock(agentId, filePath)   → CLEAN
// ← race window: another agent could write here
writeFile(filePath, content)
Between the verify call and the write, another process could modify the file. guarded_write closes that window entirely because the check and the write happen inside the same mutex-protected operation on the server.

Example

// 1. Lock the file
const lock = await propose_file_access({
  filePath: "src/auth.ts",
  agentId: "dana-claude-code",
  intent: "Refactor to JWT-based auth"
});
// → { status: "GRANTED" }

// 2. Make changes in memory
const current = readFile("src/auth.ts");
const updated = applyJwtRefactor(current);

// 3. Write atomically through the lock
const result = await guarded_write({
  agentId: "dana-claude-code",
  filePath: "src/auth.ts",
  content: updated
});

if (result.status === "WRITTEN") {
  // Success — lock hash refreshed, safe to call complete_job
}

if (result.status === "CONFLICT") {
  // File changed under us — re-read and reconcile
  const latest = readFile("src/auth.ts");
  const merged = reconcile(latest, updated);
  await guarded_write({
    agentId: "dana-claude-code",
    filePath: "src/auth.ts",
    content: merged
  });
}

Handling CONFLICT

A CONFLICT result means the file was modified by something outside your lock after the lock was granted. The right response is always to reconcile, never to retry blindly:
1

Re-read the file from disk

The current on-disk version may include work from another agent or an external process that must be preserved.
2

Merge your changes into the current version

Identify what you changed and apply those changes to the current file content. Do not simply overwrite with your original content.
3

Re-lock if your lock has expired

If significant time has passed, call propose_file_access again before retrying the write.
4

Retry guarded_write with the merged content

The new hash comparison will be against the current file (which you just read), so the retry will succeed as long as no further concurrent write occurred.

AXIS_ENFORCE_LOCKS mode

When the environment variable AXIS_ENFORCE_LOCKS=1 is set, Axis chmods a locked file to read-only at lock-grant time. Any process — including one that does not use Axis at all — will receive EACCES on a direct write attempt. guarded_write is the only safe path to write the file while it is locked, because it handles the permission restore-and-re-apply cycle internally.
With AXIS_ENFORCE_LOCKS=1 enabled, writing a locked file through your editor or any tool other than guarded_write will fail with a permission error. This is intentional. Use guarded_write for all writes while a lock is active, or disable enforcement for that session.

Build docs developers (and LLMs) love