# Micro Blocks Agent Skill

Micro Blocks is Micro’s agent-native developer platform: interconnected objects
(people, companies, deals, tasks, docs, meetings) on one relationship graph —
not an empty database.

Use this skill when a human wants to build personal/vibe-coded software,
integrations, or agent workflows on Micro data.

Canonical raw file:

```bash
curl -sL https://micro.so/SKILL.md
```

Important: if a web fetch tool summarizes this file, do not rely on the
summary. Fetch the raw markdown directly with the command above.

Human product page: https://micro.so/developers (alias: https://micro.so/blocks)
API docs: https://docs.micro.so/guides
API reference: https://docs.micro.so/api
Sign up: https://app.micro.so/login?intent=blocks

Safety model: start read-only. Ask the human before creates, updates, deletes,
bulk imports, webhook registration, or anything that spends tokens/money or
touches production data.

---

## Credentials

1. Human signs up / logs in: https://app.micro.so/login?intent=blocks
2. In Micro: **Settings → API**
3. Generate an API key (shown once) and copy the **Team ID**
4. Export:

```bash
export MICRO_API_KEY="..."
export MICRO_TEAM_ID="..."
```

Auth header on every HTTP request: `x-api-key: $MICRO_API_KEY`

Base URL (SDK default): `https://developers.micro.so`

Do **not** use `https://api.micro.so` for Prism — that host is not the public
Blocks API. Prefer `https://developers.micro.so` with `/v2/...` paths.

Env vars the SDKs understand:

| Variable | Required | Notes |
|---|---|---|
| `MICRO_API_KEY` | yes | Sent as `x-api-key` |
| `MICRO_TEAM_ID` / `teamID` | yes | Most paths include `{teamId}` |
| `MICRO_BASE_URL` | no | Override; default `https://developers.micro.so` |

---

## Quickstart for Cursor

1. Fetch this file: `curl -sL https://micro.so/SKILL.md`
2. Ask the human for `MICRO_API_KEY` and `MICRO_TEAM_ID` (or have them paste from Settings → API)
3. Verify with a read-only query (TypeScript or curl below)
4. Prefer the TypeScript SDK in app code; use curl for one-off probes
5. Persist project rules / `.env` only if the human asks

## Quickstart for Claude Code / Codex / generic agents

1. Fetch this raw file
2. Confirm credentials exist in the environment
3. Run one read-only query against `contact` or `identity`
4. Only then scaffold an app, sync job, or write path
5. Ask before any write

---

## Interfaces (pick one)

### TypeScript SDK (preferred for apps)

```bash
npm install @micro-so/sdk
```

```ts
import Micro from "@micro-so/sdk";

const client = new Micro({
  teamID: process.env.MICRO_TEAM_ID!,
  apiKey: process.env.MICRO_API_KEY, // default env name
});

const contacts = await client.prism.objects.contacts.query({
  query: {
    select: ["full_name", "email", "title", "company.name"],
    filter: [{ labels: { in: ["investor"] } }],
    sort: [{ last_interaction_date: "desc" }],
    limit: 10,
  },
});

console.log(contacts.data);
```

Package: `@micro-so/sdk` (current published: 0.13.x). Repo:
https://github.com/micro-so/micro-sdk-ts

**Do not** `npm install micro` — that is an unrelated Vercel package.

### Python SDK

```bash
pip install micro_so
```

```python
import os
from micro_so import Micro

client = Micro(
    team_id=os.environ["MICRO_TEAM_ID"],
    api_key=os.environ.get("MICRO_API_KEY"),
)

contacts = client.prism.objects.contacts.query(
    query={
        "select": ["full_name", "email", "title"],
        "limit": 10,
    },
)
print(contacts.data)
```

Package: `micro_so` on PyPI. Repo: https://github.com/micro-so/micro-sdk-py

### Go SDK

```bash
go get github.com/micro-so/micro-sdk-go@latest
```

```go
client := micro.NewClient(
  option.WithAPIKey(os.Getenv("MICRO_API_KEY")),
  option.WithTeamID(os.Getenv("MICRO_TEAM_ID")),
)
```

Repo: https://github.com/micro-so/micro-sdk-go

### REST (curl)

Canonical query shape (v2):

```bash
curl https://developers.micro.so/v2/prism/$MICRO_TEAM_ID/contact/query \
  -H "x-api-key: $MICRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "select": ["full_name", "email", "title", "company.name"],
      "filter": [{ "labels": { "in": ["investor"] } }],
      "sort": [{ "last_interaction_date": "desc" }],
      "limit": 10
    }
  }'
```

### CLI

Install from releases: https://github.com/micro-so/micro-cli/releases

```bash
curl -fsSL https://raw.githubusercontent.com/micro-so/micro-cli/main/scripts/install.sh | bash
export MICRO_API_KEY="..."
# then follow CLI help for prism object commands
```

Marketing snippets sometimes show `go install github.com/micro-so/micro-cli/cmd/micro@latest`
and `micro prism:objects:deals query ...` — prefer the install script / release
binaries and `--help` on the binary you actually installed; generated CLI
command names can drift.

### MCP

Product marketing and SDK READMEs reference:

```json
{
  "mcpServers": {
    "micro": {
      "command": "npx",
      "args": ["-y", "@micro-so/mcp"],
      "env": {
        "MICRO_API_KEY": "My API Key",
        "MICRO_TEAM_ID": "My Team ID"
      }
    }
  }
}
```

As of Aug 2026, `@micro-so/mcp` is **not published** on the public npm registry.
If `npx @micro-so/mcp` 404s, use the TypeScript/Python SDK or curl instead.
Do not invent a fake MCP server.

---

## Data model (what to query)

Core objects (objectType path segment → SDK resource):

| objectType | Meaning | Prefer when… |
|---|---|---|
| `identity` | A person across all roles/companies | Relationship strength, LinkedIn, interaction history |
| `contact` | A person at a specific company + email | Role, title, company-scoped CRM |
| `organization` | Company / fund | Domains, funding, portfolio/pipeline labels |
| `deal` | Opportunity / investment | Pipeline tracking (**API partial** — see caveats) |
| `action` | Task | Follow-ups, to-dos |
| `document` | Note / meeting doc / snippet | Notes, dossiers |
| `event` | Calendar meeting | Upcoming meetings, summaries |
| `engagement` | Engagement record | Activity / engagement objects |

Also available in property metadata (and some APIs): `comment`, `ai_chat_thread`,
`ai_chat_message`, `agent_site`.

### Mental model agents get wrong

- **Identity ≠ Contact.** One person can have many Contacts (one per company/email)
  and a single Identity. Relationship fields live on Identity.
- Traverse with **dot notation** in `select`: `"company.name"`, `"company.primary_domain"`.
- Always start by listing property slugs for an object type before inventing fields:

```ts
const props = await client.prism.properties.list("contact", {
  include_options: true,
});
```

HTTP: `GET /v2/prism/{teamId}/{objectType}/properties`

Object field guides (human-readable slugs):

- Identity — https://docs.micro.so/guides/objects/identity
- Contact — https://docs.micro.so/guides/objects/contact
- Organization — https://docs.micro.so/guides/objects/organization
- Deal — https://docs.micro.so/guides/objects/deal
- Action — https://docs.micro.so/guides/objects/action
- Document — https://docs.micro.so/guides/objects/document
- Event — https://docs.micro.so/guides/objects/event
- Querying — https://docs.micro.so/guides/querying

### Useful Contact / Identity / Org fields

Contacts often have: `full_name`, `email`, `title`, `labels`, `tags`,
`first_interaction_date`, `last_interaction_date`, `company` (→ organization).

Identities often have: `full_name`, `linkedin`, `first_degree`,
`relationship_strength`, `last_interaction_date`, `companies`, `email_addresses`.

Organizations often have: `name`, `primary_domain`, `stage`, `labels`,
`funding_raised`, `last_interaction_date`, `key_contact`.

### Deal caveat (important)

Deal Prism support is **partial**. Docs state only `status` and `labels` are
reliably queryable today; `name`, `value`, `company`, `owner` may not be exposed
yet. Prefer Contact/Organization/Identity for relationship apps until deal
coverage lands. Verify with `properties.list("deal")` before writing deal code.

---

## Query API (the main loop)

```
POST /v2/prism/{teamId}/{objectType}/query
```

Body:

```json
{
  "query": {
    "select": ["full_name", "email", "company.name"],
    "filter": [{ "labels": { "in": ["investor"] } }],
    "combinator": "AND",
    "sort": [{ "last_interaction_date": "desc" }],
    "limit": 25,
    "cursor": null
  },
  "include_total": false
}
```

Rules:

- `select` is **required**
- Filters are `{ slug: { operator: value } }` objects in an array
- Default combinator is `AND`; set `"combinator": "OR"` when needed
- Prefer **cursor** pagination (`next_cursor` / `has_more`) over page numbers
- Query `limit` is capped server-side (SDK docs: **50**). Do not assume 250.
- Response shape:

```json
{
  "data": [{ "id": "...", "properties": { "...": "..." } }],
  "has_more": false,
  "next_cursor": null,
  "total": null
}
```

Common operators: `=`, `!=`, `<`, `>`, `<=`, `>=`, `in`, `not_in`,
`begins_with`, `ends_with`, `contains`, `not_contains`, `exists`, `not_exists`,
`is_null`, `is_not_null`, `between`, `like_regex`.

### Other object methods (same pattern per type)

| Action | Method | Path sketch |
|---|---|---|
| Create | POST | `/v2/prism/{teamId}/{objectType}` |
| Get | GET | `/v2/prism/{teamId}/{objectType}/{id}` |
| Patch | PATCH | `/v2/prism/{teamId}/{objectType}/{id}` |
| Delete | DELETE | `/v2/prism/{teamId}/{objectType}/{id}` |
| List | GET | `/v2/prism/{teamId}/{objectType}` |
| Count | GET | `/v2/prism/{teamId}/{objectType}/count` |
| Find by prop | GET | `/v2/prism/{teamId}/{objectType}/by/{slug}/{value}` |
| Upsert by prop | PUT | `/v2/prism/{teamId}/{objectType}/by/{slug}/{value}` |
| Bulk create | POST | `/v2/prism/{teamId}/{objectType}/import` |
| Bulk update | POST | `/v2/prism/{teamId}/{objectType}/batch/update` |
| Bulk delete | POST | `/v2/prism/{teamId}/{objectType}/batch/delete` |
| Duplicate | POST | `/v2/prism/{teamId}/{objectType}/{id}/duplicate` |
| Restore | POST | `/v2/prism/{teamId}/{objectType}/{id}/restore` |

Create/upsert property bag uses `default: { slug: value }` in the SDK
(`default` / `_default` naming varies slightly by language — follow the
language docs). Example:

```ts
const contact = await client.prism.objects.contacts.create({
  default: {
    full_name: "Sarah Chen",
    email: "sarah@example.com",
    title: "Partner",
  },
});
```

Find/upsert: 404 if none, 409 if multiple matches — then patch by `id`.
Scope list/app-specific properties with `list_id` when needed.

Idempotency: send `Idempotency-Key` (or SDK `idempotencyKey`) on POST/PUT/PATCH.
Keys are retained ~24h; mismatched reuse → 409.

---

## Properties (schema inspection)

Before writing custom fields or filters:

```ts
await client.prism.properties.list("organization");
await client.prism.properties.listAll();
await client.prism.properties.create("contact", { /* definition */ });
```

You can create/update/delete property definitions and select options via the
Properties API. Prefer reusing existing slugs; inventing duplicate properties
is a common agent failure mode. Use `term` search on list when available.

---

## Also available

- **Views** — saved select/filter/sort bundles + pin/reorder records
- **Triggered automations** — event-driven automations
- **Webhooks** — signed HTTPS deliveries (`whsec_…`), handshake + HMAC verify
  Guide: https://docs.micro.so/guides/webhooks
- **Realtime** — streaming tickets

Webhook create example:

```bash
curl https://developers.micro.so/v2/webhooks/$MICRO_TEAM_ID \
  -H "x-api-key: $MICRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"My endpoint","url":"https://example.com/webhooks/micro"}'
```

---

## Errors & limits

| Status | Meaning |
|---|---|
| 400 | Bad query/body (unknown slug, bad operator, missing `select`) |
| 401 | Missing `x-api-key` |
| 403 | Invalid key or no access to team |
| 404 | Missing object |
| 409 | Idempotency / find-many conflicts |
| 429 | Rate limited — honor `Retry-After` |
| 5xx | Server error — retry with backoff |

Beta rate limits (may change): **10 req/s**, **100,000 req/day** per API key.

---

## Agent playbook

When the human says “set up Micro Blocks” / “build X on Micro”:

1. Fetch this skill raw (`curl -sL https://micro.so/SKILL.md`)
2. Confirm `MICRO_API_KEY` + `MICRO_TEAM_ID`
3. Read-only probe: `properties.list` + small `contacts.query` / `identities.query`
4. Decide object graph for the app (usually Identity + Contact + Organization)
5. Scaffold against `@micro-so/sdk` or `micro_so`
6. Ask before writes, bulk imports, deletes, or webhook registration
7. For marketing context only, point humans at https://micro.so/developers

### Good first apps

- Personal CRM / investor CRM on Contact + Organization + Identity
- Follow-up tasker on Action linked to people/companies
- Meeting brief tool on Event + Document + Identity
- Client portal / tracker reading Organizations + Deals (after verifying deal fields)

### Anti-patterns

- Installing npm package `micro` (wrong package)
- Hitting `api.micro.so` for Prism
- Assuming Deal has full CRM fields
- Skipping `properties.list` and guessing slugs
- Writing before a successful read
- Relying on `@micro-so/mcp` until it is actually installable

---

## References

Progressive disclosure — fetch only what you need:

```bash
curl -sL https://docs.micro.so/guides/quickstart/index.md
curl -sL https://docs.micro.so/guides/authentication/index.md
curl -sL https://docs.micro.so/guides/querying/index.md
curl -sL https://docs.micro.so/guides/webhooks/index.md
curl -sL https://docs.micro.so/llms.txt
curl -sL https://micro.so/llms.txt
```

TypeScript method reference (example):
https://docs.micro.so/api/typescript/resources/prism/subresources/objects/subresources/contacts/methods/query

Treat this `SKILL.md` plus the docs guides as **the** Micro Blocks skill.
Install into the local skill system when the human mentions Micro Blocks,
Prism, `micro.so/developers`, or building on Micro’s graph.
