> ## Documentation Index
> Fetch the complete documentation index at: https://cognitio-agent.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Extract structured data

> Extract a contact into JSON and validate it with Zod.

Turn a short contact description into a typed object that your application can validate. The complete code is below. You can also [browse the project on GitHub](https://github.com/ozgurugurlu/cognitio-agent-sdk/tree/main/examples/02-structured-output) or [open its JavaScript source](https://github.com/ozgurugurlu/cognitio-agent-sdk/blob/main/examples/02-structured-output/index.mjs).

## 1. Create the project

Use Node.js 22 or newer, npm, and an OpenAI API key with access to `gpt-4.1-mini`. Model requests use your provider account and can incur charges.

```sh theme={null}
mkdir cognitio-extraction
cd cognitio-extraction
npm init -y
npm install --save-exact cognitio-agent-sdk@2.0.1 zod@4.1.8
```

Keep npm optional dependencies enabled; they include the runtime for your platform. You do not need a separately installed runtime.

## 2. Configure the environment

Create a file named `.env` in this directory:

```dotenv theme={null}
COGNITIO_MODEL=openai/gpt-4.1-mini
OPENAI_API_KEY=replace_with_your_key
```

Replace the placeholder with your key. Add `.env` and `node_modules/` to `.gitignore`. Existing shell environment values take precedence over this file. To use Anthropic instead, set `COGNITIO_MODEL=anthropic/claude-sonnet-4-5` and `ANTHROPIC_API_KEY` to your Anthropic key; the code forwards either provider's credential.

## 3. Create `index.mjs`

```js theme={null}
import { Agent, defineOutputFormat } from "cognitio-agent-sdk"
import { z } from "zod"

const model = process.env.COGNITIO_MODEL?.trim() || "openai/gpt-4.1-mini"
const credential = { openai: "OPENAI_API_KEY", anthropic: "ANTHROPIC_API_KEY" }[model.split("/")[0]]
if (!model.includes("/")) throw new Error("Set COGNITIO_MODEL to a provider/model identifier.")
if (credential && (!process.env[credential]?.trim() || process.env[credential] === "replace_with_your_key")) {
  throw new Error(`Set ${credential} in .env or your shell before running this example.`)
}
const providerEnv = Object.fromEntries(
  ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]
    .filter((name) => process.env[name]?.trim())
    .map((name) => [name, process.env[name]]),
)

const contactSchema = z.object({
  name: z.string().min(1),
  email: z.email(),
  company: z.string().min(1),
})
// Keep the model-facing email schema simple; validate the actual address below.
const modelSchema = contactSchema.extend({
  email: z.string().describe("Email address exactly as written in the input"),
})
const agent = new Agent({
  model,
  instructions: "Extract only information present in the supplied text.",
  settingSources: [],
  includeEnvironment: false,
  allowedTools: ["StructuredOutput"],
  outputFormat: defineOutputFormat(modelSchema, { maxRetries: 1 }),
  maxTurns: 3,
  maxBudgetUsd: 0.03,
  spawn: {
    isolated: true,
    port: 0,
    autoCleanup: true,
    env: { ...providerEnv, COGNITIO_DISABLE_AUTOUPDATE: "1", COGNITIO_DISABLE_LSP_DOWNLOAD: "1" },
    config: { plugin: [], lsp: false, formatter: false, agent: { title: { disable: true } } },
  },
})

try {
  const result = await agent.run("Extract this contact: Mina Patel works at Acme Labs. Email: mina@example.com.", {
    signal: AbortSignal.timeout(90_000),
  })
  if (result.isError || result.subtype !== "success") {
    throw new Error(`Extraction failed: ${result.subtype}: ${result.error?.message ?? "No error details"}`)
  }
  const contact = contactSchema.parse(result.structuredOutput)
  console.log(JSON.stringify(contact, null, 2))
} finally {
  await agent.close()
}
```

## 4. Run it

```sh theme={null}
node --env-file=.env index.mjs
```

The fixed input should produce:

```json theme={null}
{
  "name": "Mina Patel",
  "email": "mina@example.com",
  "company": "Acme Labs"
}
```

The application prints the object only after a successful result and `contactSchema.parse()`. A schema error or an unsuccessful model result exits with an error. Replace the contact sentence passed to `agent.run()` with your own input.

## How it works

`defineOutputFormat(modelSchema)` supplies a simple model-facing shape. The stricter local `contactSchema` checks the actual email address after the response. This keeps provider-facing schema constraints separate from application validation. Read `result.structuredOutput`; do not parse `result.text` as a substitute.

`allowedTools: ["StructuredOutput"]` permits only the runtime's schema-output tool. Its name is case-sensitive. `disallowedTools: ["*"]` would block this tool too. This example allows three turns and one schema retry; retries also consume turns and model usage. The estimated \$0.03 budget is not a provider billing limit.

The explicit `spawn` configuration creates a dedicated runtime, which `agent.close()` stops in `finally`. Each request has a 90-second cancellation deadline. A valid object can still contain an incorrect extracted fact, so validate any additional rules your application requires. See [structured output](https://cognitio-agent.mintlify.site/concepts/structured-output.md).

## Use the existing project

If you prefer the [complete GitHub project](https://github.com/ozgurugurlu/cognitio-agent-sdk/tree/main/examples/02-structured-output), copy that directory, run `npm ci`, copy `.env.example` to `.env`, set your key, and run `npm start`. On PowerShell, use `Copy-Item .env.example .env`; in a Unix shell, use `cp .env.example .env`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.