Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cc62fb3
chore(python): regenerate CreateAgentRequest with PLANNER/INVENTORY enum
pmbrull Apr 29, 2026
a43cb43
wip(python): add DefaultAgentHandle (test still failing pending Task 6)
pmbrull Apr 29, 2026
b6ec1a9
feat(python): client.agent() with no name uses the default agent
pmbrull Apr 29, 2026
2971c17
test(python): cover streaming and async paths for default agent
pmbrull Apr 29, 2026
dd2d1c5
feat(typescript): client.agent() with no name uses the default agent
pmbrull Apr 29, 2026
4fe5a19
feat(java): client.agent() with no name uses the default agent
pmbrull Apr 29, 2026
0ffe14d
feat(cli): support default-agent invocation via --default flag
pmbrull Apr 29, 2026
c5e5739
feat(n8n): add Use Default Agent option to AISdkAgent node
pmbrull Apr 29, 2026
11f344f
docs: document client.agent() default-agent usage across SDKs
pmbrull Apr 29, 2026
0f11a50
chore(n8n): bump @openmetadata/ai-sdk dep to ^0.1.2
pmbrull Apr 29, 2026
b17ee5f
feat(sdk): surface thinking_steps in InvokeResponse across all SDKs
pmbrull Apr 30, 2026
5925788
feat(python): scaffold api/ package for namespace classes
pmbrull Apr 30, 2026
29a11a9
feat(python): add ContextMemory, CreateContextMemoryRequest, search m…
pmbrull Apr 30, 2026
6883c45
feat(python): MemoriesAPI with list/get/create/delete/search
pmbrull Apr 30, 2026
6b5f147
refactor(python): move agent/bot/persona/ability CRUD into namespace …
pmbrull Apr 30, 2026
f8a6090
refactor(python)!: move all CRUD onto namespaces (BREAKING)
pmbrull Apr 30, 2026
59ee271
feat(python): export memory models + integration test
pmbrull Apr 30, 2026
2505096
docs: add CHANGELOG and update API examples for namespace pattern
pmbrull Apr 30, 2026
347eb2c
feat(cli): add memories subcommand for Context Center CRUD + search
pmbrull Apr 30, 2026
7340e80
feat(java): add Context Center memory models
pmbrull Apr 30, 2026
2d95c78
feat(java): add per-entity API namespace classes
pmbrull Apr 30, 2026
2b9b0f7
refactor(java): replace AISdk flat methods with namespace accessors
pmbrull Apr 30, 2026
edc667b
feat(typescript): add Context Center memory types
pmbrull Apr 30, 2026
f8dee82
feat(typescript): add per-entity API namespace classes
pmbrull Apr 30, 2026
c4665e0
refactor(typescript): replace AISdk flat methods with namespace acces…
pmbrull Apr 30, 2026
8f6a3fc
chore(python): apply ruff format
pmbrull Apr 30, 2026
71b05b8
chore: ignore docs/superpowers (local design specs and plans)
pmbrull Apr 30, 2026
28414d9
docs: document client.memories API across all SDKs
pmbrull Apr 30, 2026
82b5c0a
feat(cli): default AskCollate entry at top of agent selection menu
pmbrull Apr 30, 2026
7e48f8b
chore(cli): drop description line from AskCollate menu entry
pmbrull Apr 30, 2026
3158821
fix(cli): render thinking steps one per line in TUI and invoke output
pmbrull Apr 30, 2026
49934bc
feat(cli): render markdown links + apply markdown to thinking steps
pmbrull Apr 30, 2026
7e15192
docs: update API reference and cookbook docs for namespace structure
pmbrull Apr 30, 2026
a7df37e
fix: don't apply request timeout to SSE streams across all SDKs
pmbrull Apr 30, 2026
2bf5e7e
fix(ci): adapt to newer toolchain versions in CI
pmbrull Apr 30, 2026
1fbf4c6
chore: bump version to 0.2.0
pmbrull Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# =============================================================================

docs/plans/**
docs/superpowers/**

# =============================================================================
# Python
Expand Down
57 changes: 57 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

### Added

- `client.memories` namespace with `list`, `get`, `create`, `delete`, and
`search` (hybrid NLQ search over the `contextMemory` index) for Context
Center memories. All methods support sync and async in Python and async in
TypeScript; sync-only in Java; subcommands in the Rust CLI.
- Memory model types across all SDKs: `ContextMemory`,
`CreateContextMemoryRequest`, `MemorySearchHit`, `MemorySearchResults`,
`MemoryType`, `MemoryScope`, `MemoryVisibility`.
- `CHANGELOG.md` for release notes.

### Changed (BREAKING)

All client CRUD methods now live on namespaces. The `client.agent(name)`
handle factory and `client.mcp` namespace are unchanged.

**Python migration:**

| Old (removed) | New |
| ---------------------------- | ------------------------------ |
| `client.list_agents()` | `client.agents.list()` |
| `client.create_agent(req)` | `client.agents.create(req)` |
| `client.list_bots()` | `client.bots.list()` |
| `client.get_bot(name)` | `client.bots.get(name)` |
| `client.list_personas()` | `client.personas.list()` |
| `client.get_persona(name)` | `client.personas.get(name)` |
| `client.create_persona(req)` | `client.personas.create(req)` |
| `client.list_abilities()` | `client.abilities.list()` |
| `client.get_ability(name)` | `client.abilities.get(name)` |

All `aXxx` async variants follow the same pattern: `client.X.aYyy()`.

**TypeScript migration:**

Same shape as Python with camelCase methods and accessed as fields
(`client.agents.list()`, `client.bots.get(name)`, etc.).

**Java migration:**

Namespaces are exposed as methods rather than fields:
`client.agents().list()`, `client.bots().get(name)`,
`client.memories().search(query)`, etc.

**Rust CLI:**

The CLI was already namespace-shaped via subcommands. New `memories`
subcommand added: `ai-sdk memories list`, `ai-sdk memories search "..."`,
etc.
20 changes: 18 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,27 @@ make install-hooks # Install pre-commit hooks

```
client = AISdk(host, token)

# default AskCollate agent
response = client.agent().invoke("message")

# Named dynamic agent
response = client.agent("agent-name").invoke("message")

# Streaming
for event in client.agent("agent-name").stream("message"):
# Streaming (works with both)
for event in client.agent().stream("message"):
handle(event)

# Entity CRUD lives on namespaces (composition pattern)
client.agents.list()
client.bots.get("ingestion-bot")
client.personas.list()
client.abilities.get("DataQuality")

# Context Center memories
client.memories.list(primary_entity_fqn="db.tbl")
client.memories.create(CreateContextMemoryRequest(name="m1", question="...", answer="..."))
results = client.memories.search("explain customer churn")
```

### Event Types (Streaming)
Expand Down
161 changes: 153 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,18 @@ from ai_sdk import AISdk, AISdkConfig
config = AISdkConfig.from_env() # reads AI_SDK_HOST and AI_SDK_TOKEN
client = AISdk.from_config(config)

# Invoke an agent
# default AskCollate agent
response = client.agent().call("What data quality tests should I add?")
print(response.response)

# Named dynamic agent
response = client.agent("DataQualityPlannerAgent").call(
"What data quality tests should I add for the customers table?"
)
print(response.response)

# Stream responses in real time
for event in client.agent("DataQualityPlannerAgent").stream("Analyze the orders table"):
# Stream responses in real time (works with both)
for event in client.agent().stream("Analyze the orders table"):
if event.type == "content":
print(event.content, end="", flush=True)
```
Expand All @@ -96,13 +100,18 @@ const client = new AISdk({
token: 'your-bot-jwt-token'
});

const response = await client.agent('DataQualityPlannerAgent').call(
// default AskCollate agent
const defaultResponse = await client.agent().invoke('What tables have quality issues?');
console.log(defaultResponse.response);

// Named dynamic agent
const response = await client.agent('DataQualityPlannerAgent').invoke(
'What data quality tests should I add for the customers table?'
);
console.log(response.response);

// Stream responses
for await (const event of client.agent('DataQualityPlannerAgent').stream('Analyze data quality')) {
// Stream responses (works with both)
for await (const event of client.agent().stream('Analyze data quality')) {
if (event.type === 'content') {
process.stdout.write(event.content || '');
}
Expand All @@ -129,8 +138,14 @@ AISdk client = new AISdk.Builder()
.token("your-bot-jwt-token")
.build();

// default AskCollate agent
InvokeResponse defaultResponse = client.agent()
.invoke("What data quality tests should I add?");
System.out.println(defaultResponse.getResponse());

// Named dynamic agent
InvokeResponse response = client.agent("DataQualityPlannerAgent")
.call("What data quality tests should I add?");
.invoke("What data quality tests should I add?");
System.out.println(response.getResponse());
```

Expand All @@ -143,12 +158,142 @@ curl -sSL https://raw.githubusercontent.com/open-metadata/ai-sdk/main/cli/instal
# Configure
ai-sdk configure

# Invoke an agent
# default AskCollate agent
ai-sdk invoke --default "Analyze the customers table"

# Named dynamic agent
ai-sdk invoke DataQualityPlannerAgent "Analyze the customers table"
```

Interactive TUI with markdown rendering and syntax highlighting.

## Context Memories

OpenMetadata's **Context Center** stores reusable knowledge — user preferences, use cases, runbooks, and FAQs — that any AI agent can read on demand. Each memory has a canonical question/answer pair, a type, and an optional `primaryEntity` so it can be retrieved when working with a specific table, dashboard, or pipeline.

The `client.memories` namespace exposes the full lifecycle. **Hybrid search** combines vector similarity with keyword ranking over the `contextMemory` index — pass a natural-language query and an optional filter map; you get back hits ranked by relevance.

### Python

```python
from ai_sdk import AISdk, CreateContextMemoryRequest, MemoryType, MemoryVisibility

client = AISdk.from_config(AISdkConfig.from_env())

# Create a memory tied to a specific table
created = client.memories.create(CreateContextMemoryRequest(
name="orders-grain",
title="Orders grain",
question="What is the grain of the orders table?",
answer="One row per order_id; payments roll up to this grain.",
memory_type=MemoryType.NOTE,
visibility=MemoryVisibility.SHARED,
primary_entity=EntityReference(id="<table-uuid>", type="table"),
))

# List memories attached to that asset
for m in client.memories.list(primary_entity_fqn="prod.warehouse.orders"):
print(m.title)

# Hybrid NLQ search
results = client.memories.search("how do we measure order volume", size=5)
for hit in results.hits:
print(f"[{hit.score:.2f}] {hit.memory.title}")

# Soft delete (use hard_delete=True to remove permanently)
client.memories.delete(created.id)
```

### TypeScript

```typescript
const created = await client.memories.create({
name: 'orders-grain',
title: 'Orders grain',
question: 'What is the grain of the orders table?',
answer: 'One row per order_id; payments roll up to this grain.',
memoryType: 'Note',
visibility: 'Shared',
primaryEntity: { id: '<table-uuid>', type: 'table' },
});

for (const m of await client.memories.list({ primaryEntityFqn: 'prod.warehouse.orders' })) {
console.log(m.title);
}

const results = await client.memories.search('how do we measure order volume', { size: 5 });
for (const hit of results.hits) {
console.log(`[${hit.score.toFixed(2)}] ${hit.memory.title}`);
}

await client.memories.delete(created.id);
```

### Java

```java
import io.openmetadata.ai.models.*;

ContextMemory created = client.memories().create(
CreateContextMemoryRequest.builder()
.name("orders-grain")
.title("Orders grain")
.question("What is the grain of the orders table?")
.answer("One row per order_id; payments roll up to this grain.")
.memoryType(MemoryType.NOTE)
.visibility(MemoryVisibility.SHARED)
.primaryEntity(EntityReference.builder().id("<table-uuid>").type("table").build())
.build()
);

for (ContextMemory m : client.memories().list("prod.warehouse.orders", null)) {
System.out.println(m.getTitle());
}

MemorySearchResults results = client.memories().search(
"how do we measure order volume", null, 5, 0
);
for (MemorySearchHit hit : results.getHits()) {
System.out.printf("[%.2f] %s%n", hit.getScore(), hit.getMemory().getTitle());
}

client.memories().delete(created.getId());
```

### CLI

```bash
# Create
ai-sdk memories create \
--name orders-grain \
--title "Orders grain" \
--question "What is the grain of the orders table?" \
--answer "One row per order_id; payments roll up to this grain." \
--memory-type note \
--visibility shared \
--primary-entity-id <table-uuid> --primary-entity-type table

# List by entity
ai-sdk memories list --entity-fqn prod.warehouse.orders

# Hybrid NLQ search (use --json to pipe into jq)
ai-sdk memories search "how do we measure order volume" --size 5 --json

# Delete (add --hard for permanent)
ai-sdk memories delete <memory-id>
```

**Filtering search results.** Pass a JSON filter map to scope by entity, visibility, or any indexed field:

```python
client.memories.search(
"explain churn",
filters={"primaryEntityId": ["<uuid>"], "visibility": ["Entity", "Shared"]},
)
```

See each SDK's README for the full surface (sync + async, all enum values, model fields).

## Cookbook

Real-world examples showing how teams use the AI SDK in production workflows.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.2
0.2.0
8 changes: 8 additions & 0 deletions cli/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,16 @@ The `chat` command launches an interactive terminal interface:
ai-sdk chat # Opens agent selector
ai-sdk chat AgentName # Opens chat with specific agent
ai-sdk chat AgentName -c <conv-id> # Resume conversation
ai-sdk chat --debug # Log SSE events to ~/.ai-sdk/chat-debug.log
ai-sdk chat --debug /tmp/sse.log # Log SSE events to a custom path
```

The `--debug` flag truncates the log on session start and appends events from
every stream within the session — useful for diagnosing issues like
`Network error: error decoding response body` mid-stream. The log captures
each SSE event, message-level details, and the underlying error and unparsed
buffer when the stream is cut short.

### TUI Features

- **Agent selection menu**: `/agents` or start without agent name
Expand Down
Loading
Loading