> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentoffice.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

## Building a Contract Review Agent

Let's build an AI agent that reviews and edits NDAs. If you don't have an API key yet, [sign up for free](https://agentoffice.dev/dashboard).

### Step 1: Upload the Document

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { AgentOffice } from "agent-office-sdk";
  import fs from "fs";

  const client = new AgentOffice({
    apiKey: "YOUR_API_KEY",
  });

  const fileBuffer = fs.readFileSync("nda.docx");
  const file = new File([fileBuffer], "nda.docx", {
    type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });

  const { docId, markdown } = await client.documents.create({
    file: file,
    returnMarkdown: true,
  });
  ```

  ```python Python theme={null}
  from agent_office import AgentOffice

  client = AgentOffice(api_key="YOUR_API_KEY")

  doc = client.documents.create(
      file="nda.docx",
      return_markdown=True
  )

  doc_id = doc.doc_id
  markdown = doc.markdown
  ```
</CodeGroup>

### Step 2: Create Agent Tools

<CodeGroup>
  ```typescript TypeScript (Vercel AI SDK) theme={null}
  import { z } from "zod";
  import { randomUUID } from "crypto";

  const tools = {
    readFile: {
      description:
        "Use this tool to read the current state of the document as markdown.",
      parameters: z.object({}),
      execute: async () => {
        const result = await client.read({
          docId: docId,
          readUid: randomUUID(),
        });
        return result.markdown;
      },
    },
    editFile: {
      description:
        "Use this tool to directly apply an edit to a small section or paragraph of the document. All changes will be applied immediately, this tool should not be used for adding tracked changes or comments.",
      parameters: z.object({
        editInstructions: z
          .string()
          .describe(
            "Give clear instructions of the edit to be made. Use first-person, clear descriptions."
          ),
        lookupText: z
          .string()
          .optional()
          .describe(
            "A unique text snippet from the section to edit. Provide the exact wording without markdown formatting. Matching uses only alphanumeric characters, so choose distinctive words that uniquely identify the location."
          ),
      }),
      execute: async ({ editInstructions, lookupText }) => {
        const result = await client.edit({
          docId: docId,
          editUid: randomUUID(),
          editInstructions,
          lookupText,
        });
        return result.editApplied ? "Edit applied" : "Edit failed";
      },
    },
  };
  ```

  ```python Python (LangChain) theme={null}
  from langchain.tools import tool
  from langchain_anthropic import ChatAnthropic
  from langchain.agents import create_react_agent, AgentExecutor
  from uuid import uuid4

  @tool
  def read_file() -> str:
      """Use this tool to read the current state of the document as markdown."""
      result = client.read(doc_id=doc_id)
      return result.markdown

  @tool
  def edit_file(edit_instructions: str, lookup_text: str = None) -> str:
      """Use this tool to directly apply an edit to a small section or paragraph of the document. All changes will be applied immediately, this tool should not be used for adding tracked changes or comments.

      Args:
          edit_instructions: Give clear instructions of the edit to be made. Use first-person, clear descriptions.
          lookup_text: A unique text snippet from the section to edit. Provide the exact wording without markdown formatting. Matching uses only alphanumeric characters, so choose distinctive words that uniquely identify the location.
      """
      result = client.edit(
          doc_id=doc_id,
          edit_uid=str(uuid4()),
          edit_instructions=edit_instructions,
          lookup_text=lookup_text,
      )
      return "Edit applied" if result.edit_applied else "Edit failed"

  tools = [read_file, edit_file]
  ```
</CodeGroup>

### Step 3: Run Your Agent

<CodeGroup>
  ```typescript TypeScript (Vercel AI SDK) theme={null}
  import { generateText } from "ai";
  import { anthropic } from "@ai-sdk/anthropic";

  const result = await generateText({
    model: anthropic("claude-sonnet-4"),
    tools,
    prompt: `You are an expert legal assistant. 

  You represent Quantum Dynamics LLC (the recipient) who have just been sent an NDA by NovaTech Industries.
  This NDA has landed on your desk and you must fill in the placeholders with dummy values and make edits to the document so that Quantum Dynamics LLC is protected.

  The document content is:

  ${markdown}

  Use the editFile tool to make edits to the document.
  After making a large amount of edits, use the readFile tool to read the document and make sure the edits are applied correctly.`,
  });
  ```

  ```python Python (LangChain) theme={null}
  llm = ChatAnthropic(model="claude-sonnet-4")

  agent = create_react_agent(llm, tools, prompt_template)
  agent_executor = AgentExecutor(agent=agent, tools=tools)

  agent_executor.invoke({
      "input": f"""You are an expert legal assistant.

  You represent Quantum Dynamics LLC (the recipient) who have just been sent an NDA by NovaTech Industries.
  This NDA has landed on your desk and you must fill in the placeholders with dummy values and make edits to the document so that Quantum Dynamics LLC is protected.

  The document content is:

  {markdown}

  Use the edit_file tool to make edits to the document.
  After making a large amount of edits, use the read_file tool to read the document and make sure the edits are applied correctly."""
  })
  ```
</CodeGroup>

### Step 4: Download the Result

<CodeGroup>
  ```typescript TypeScript theme={null}
  const result = await client.documents.download({ docId: docId });

  // Download file from the presigned URL
  const fileResponse = await fetch(result.downloadUrl);
  const fileBlob = await fileResponse.blob();

  // Save to disk
  const arrayBuffer = await fileBlob.arrayBuffer();
  fs.writeFileSync("edited_nda.docx", Buffer.from(arrayBuffer));
  ```

  ```python Python theme={null}
  import requests

  result = client.documents.download(doc_id=doc_id)

  # Download the file
  file_response = requests.get(result.download_url)
  with open("edited_nda.docx", "wb") as f:
      f.write(file_response.content)
  ```
</CodeGroup>

## Full Code Example

<CodeGroup>
  ```typescript TypeScript (Vercel AI SDK) theme={null}
  import { AgentOffice } from "agent-office-sdk";
  import { generateText } from "ai";
  import { anthropic } from "@ai-sdk/anthropic";
  import { z } from "zod";
  import { randomUUID } from "crypto";
  import fs from "fs";

  // Initialize client
  const client = new AgentOffice({
    apiKey: "YOUR_API_KEY",
  });

  // Upload document
  const fileBuffer = fs.readFileSync("nda.docx");
  const file = new File([fileBuffer], "nda.docx", {
    type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });

  const { docId, markdown } = await client.documents.create({
    file: file,
    returnMarkdown: true,
  });

  // Define tools
  const tools = {
    readFile: {
      description:
        "Use this tool to read the current state of the document as markdown.",
      parameters: z.object({}),
      execute: async () => {
        const result = await client.read({
          docId: docId,
          readUid: randomUUID(),
        });
        return result.markdown;
      },
    },
    editFile: {
      description:
        "Use this tool to directly apply an edit to a small section or paragraph of the document. All changes will be applied immediately, this tool should not be used for adding tracked changes or comments.",
      parameters: z.object({
        editInstructions: z
          .string()
          .describe(
            "Give clear instructions of the edit to be made. Use first-person, clear descriptions."
          ),
        lookupText: z
          .string()
          .optional()
          .describe(
            "A unique text snippet from the section to edit. Provide the exact wording without markdown formatting. Matching uses only alphanumeric characters, so choose distinctive words that uniquely identify the location."
          ),
      }),
      execute: async ({ editInstructions, lookupText }) => {
        const result = await client.edit({
          docId: docId,
          editUid: randomUUID(),
          editInstructions,
          lookupText,
        });
        return result.editApplied ? "Edit applied" : "Edit failed";
      },
    },
  };

  // Run agent
  const result = await generateText({
    model: anthropic("claude-sonnet-4"),
    tools,
    prompt: `You are an expert legal assistant. 

  You represent Quantum Dynamics LLC (the recipient) who have just been sent an NDA by NovaTech Industries.
  This NDA has landed on your desk and you must fill in the placeholders with dummy values and make edits to the document so that Quantum Dynamics LLC is protected.

  The document content is:

  ${markdown}

  Use the editFile tool to make edits to the document.
  After making a large amount of edits, use the readFile tool to read the document and make sure the edits are applied correctly.`,
  });

  // Download result
  const downloadResult = await client.documents.download({ docId: docId });
  const fileResponse = await fetch(downloadResult.downloadUrl);
  const fileBlob = await fileResponse.blob();
  const arrayBuffer = await fileBlob.arrayBuffer();
  fs.writeFileSync("edited_nda.docx", Buffer.from(arrayBuffer));
  ```

  ```python Python (LangChain) theme={null}
  from agent_office import AgentOffice
  from uuid import uuid4
  from langchain.tools import tool
  from langchain_anthropic import ChatAnthropic
  from langchain.agents import create_react_agent, AgentExecutor
  from langchain import hub
  import requests

  # Initialize client
  client = AgentOffice(api_key="YOUR_API_KEY")

  # Upload document
  doc = client.documents.create(
      file="nda.docx",
      return_markdown=True
  )

  doc_id = doc.doc_id
  markdown = doc.markdown

  # Define tools
  @tool
  def read_file() -> str:
      """Use this tool to read the current state of the document as markdown."""
      result = client.read(doc_id=doc_id)
      return result.markdown

  @tool
  def edit_file(edit_instructions: str, lookup_text: str = None) -> str:
      """Use this tool to directly apply an edit to a small section or paragraph of the document. All changes will be applied immediately, this tool should not be used for adding tracked changes or comments.

      Args:
          edit_instructions: Give clear instructions of the edit to be made. Use first-person, clear descriptions.
          lookup_text: A unique text snippet from the section to edit. Provide the exact wording without markdown formatting. Matching uses only alphanumeric characters, so choose distinctive words that uniquely identify the location.
      """
      result = client.edit(
          doc_id=doc_id,
          edit_uid=str(uuid4()),
          edit_instructions=edit_instructions,
          lookup_text=lookup_text,
      )
      return "Edit applied" if result.edit_applied else "Edit failed"

  tools = [read_file, edit_file]

  # Run agent
  llm = ChatAnthropic(model="claude-sonnet-4")
  prompt = hub.pull("hwchase17/react")
  agent = create_react_agent(llm, tools, prompt)
  agent_executor = AgentExecutor(agent=agent, tools=tools)

  agent_executor.invoke({
      "input": f"""You are an expert legal assistant.

  You represent Quantum Dynamics LLC (the recipient) who have just been sent an NDA by NovaTech Industries.
  This NDA has landed on your desk and you must fill in the placeholders with dummy values and make edits to the document so that Quantum Dynamics LLC is protected.

  The document content is:

  {markdown}

  Use the edit_file tool to make edits to the document.
  After making a large amount of edits, use the read_file tool to read the document and make sure the edits are applied correctly."""
  })

  # Download result
  result = client.documents.download(doc_id=doc_id)
  file_response = requests.get(result.download_url)
  with open("edited_nda.docx", "wb") as f:
      f.write(file_response.content)
  ```
</CodeGroup>

## Next Steps

* [View pricing](https://agentoffice.dev/#pricing) to scale your document automation
* Learn about [tracked changes](/api-reference/documents/edit) for collaborative workflows
* Explore [image-based edits](/api-reference/documents/edit) for signatures and stamps
