Skip to content

feat(api): add taosmd.ingest()/search() to back the agent-rules contract - #60

Merged
jaylfc merged 1 commit into
masterfrom
fix/top-level-ingest-search-api
May 1, 2026
Merged

feat(api): add taosmd.ingest()/search() to back the agent-rules contract#60
jaylfc merged 1 commit into
masterfrom
fix/top-level-ingest-search-api

Conversation

@jaylfc

@jaylfc jaylfc commented May 1, 2026

Copy link
Copy Markdown
Owner

Summary

The per-turn rules block in `taosmd/docs/agent-rules.md` (which agents copy verbatim into their CLAUDE.md / AGENTS.md / system prompt at install time) told agents to call:

```python
await taosmd.ingest(transcript, agent="")
hits = await taosmd.search(query, agent="")
```

Neither function existed at the module level. An agent that followed the contract verbatim hit `AttributeError`, including the README's verify-install step (`taosmd.search('hello', agent='')`). The compact rules-block API also drifted from the long-form `AGENTS.md` integration guide which uses the underlying `archive.record()` / `vmem.search()` calls directly — agents reading both got two different stories.

This PR backs the contract with real implementations. No doc churn — the rules block, AGENTS.md, and the README install ritual all stay as-is.

What changes

  • `taosmd/api.py` — new module with `ingest()` and `search()`. Both:
    • Auto-discover `~/.taosmd` (override via `TAOSMD_DATA_DIR` or explicit `data_dir=`)
    • Honour the `config.json` written by `python -m taosmd.auto_setup`
    • Find the MiniLM ONNX model under `<data_dir>/models/minilm-onnx`, `$TAOSMD_DIR/models/minilm-onnx` (set by `scripts/setup.sh`), or `$TAOSMD_ONNX_PATH`
    • Lazy-init stores on first call, cached per resolved `data_dir`
    • Auto-register the agent if it isn't already (mirrors the auto-register behaviour described in `agents.py:15`)
  • `ingest()` — accepts a string, a `{role, content, timestamp}` dict, or any iterable of either. Shelves verbatim text into the zero-loss archive AND embeds it into vector memory so a later `search()` can reach it.
  • `search()` — calls `retrieve()` across {vector, kg, archive} and reshapes hits into the agent-rules contract shape: `{text, source, timestamp, confidence, metadata}`. Confidence is read from the underlying source score (cosine for vector, KG confidence, etc) so the documented `< 0.6` threshold reads in the right range.
  • `taosmd/init.py` — re-exports `ingest` and `search`.

What does NOT change

  • `taosmd/docs/agent-rules.md` — already accurate; this PR makes it true.
  • `AGENTS.md` — long-form integration guide still uses the lower-level API for agents that want fine-grained control. Both paths now coexist cleanly.
  • `benchmarks/`, `docs/benchmarks.md`, README — untouched.

Test plan

  • 13 new tests in `tests/test_api.py` cover: top-level export presence (regression for the agent-rules contract), ingest of str/dict/iterable, empty-content skipping, agent-required validation, search hit shape, empty query, data_dir resolution (explicit / env / default), config.json honoured, and `_format_hit` confidence-source preference
  • Full suite: 123 passing (110 prior + 13 new)
  • Tests use a tmpdir as `data_dir` and a deterministic fake embedder, so they don't need ONNX or QMD installed
  • Manual verify on a fresh `~/.taosmd` install: `python -c "import asyncio, taosmd; asyncio.run(taosmd.ingest('hi', agent='manual'))"` then `asyncio.run(taosmd.search('hi', agent='manual'))`

Summary by CodeRabbit

Release Notes

  • New Features
    • Added ingest() function to archive and index transcripts by agent
    • Added search() function to query stored data with confidence scores and metadata
    • Both functions now available directly from the taosmd package
    • Automatic data directory resolution with customizable paths
    • Search results include text, source, timestamp, and confidence metrics

The per-turn rules block in `taosmd/docs/agent-rules.md` told agents to
call `taosmd.ingest(transcript, agent="x")` and
`taosmd.search(query, agent="x")`, but neither function existed at the
module level — agents that followed the contract verbatim hit
AttributeError, including the README's verify-install step
(`taosmd.search('hello', agent='<name>')`). The compact rules-block API
also drifted from the long-form AGENTS.md guide which used the
underlying `archive.record()` / `vmem.search()` calls directly.

Adds `taosmd/api.py` with two zero-config entry points that match the
contract:

- `ingest(transcript, *, agent, data_dir=None)` — shelves verbatim text
  into the zero-loss archive AND embeds it into vector memory so a
  later `search()` can reach it. Accepts a string, a `{role, content,
  timestamp}` dict, or any iterable of either.
- `search(query, *, agent, limit=5, data_dir=None)` — calls retrieve()
  across {vector, kg, archive} and reshapes the hits into the rules-
  block contract: `{text, source, timestamp, confidence, metadata}`.
  Confidence is taken from the underlying source score (cosine for
  vector, KG confidence, etc) so the documented `< 0.6` threshold
  reads in the right range.

Both auto-discover `~/.taosmd` (override via `TAOSMD_DATA_DIR` or
explicit `data_dir=`), honour the `config.json` written by
`python -m taosmd.auto_setup`, and find the MiniLM ONNX model under
`<data_dir>/models/minilm-onnx`, `$TAOSMD_DIR/models/minilm-onnx`
(set by `scripts/setup.sh`), or `$TAOSMD_ONNX_PATH`. Stores are
lazy-initialised on first call and cached per data_dir, so concurrent
calls don't double-init.

Re-exports both from `taosmd/__init__.py`.

13 new tests cover: top-level export presence (regression for the
agent-rules contract), ingest of str/dict/iterable, empty-content
skipping, agent-required validation, search hit shape, empty query,
data_dir resolution (explicit / env / default), config.json honoured,
and the format_hit confidence-source preference. 123 tests pass.
@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR introduces a public API layer with async ingest() and search() functions to the taosmd package. These functions provide zero-config transcript ingestion and querying with automatic store initialization, caching, and data directory resolution, along with comprehensive test coverage.

Changes

Cohort / File(s) Summary
Package Exports
taosmd/__init__.py
Re-exports ingest and search functions from taosmd.api into the package's public namespace.
Core API Module
taosmd/api.py
New module implementing async ingest() and search() functions. Features include: lazy per-directory store initialization and caching (ArchiveStore, VectorMemory, TemporalKnowledgeGraph), config-aware embed mode selection with ONNX fallback support, transcript normalization and deduplication, and multi-source retrieval with formatted hit results containing text, source, timestamp, and confidence scores.
API Tests
tests/test_api.py
Comprehensive test suite validating public API exports, ingest/search behavior, store initialization, empty message filtering, data directory resolution, config loading, and hit formatting logic.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ingest as ingest()
    participant Cache as Store Cache
    participant Config as Config
    participant Archive as ArchiveStore
    participant Vector as VectorMemory
    participant KG as TemporalKnowledgeGraph

    Client->>ingest: ingest(transcript, agent, data_dir)
    ingest->>ingest: Resolve data directory
    ingest->>Config: Load config.json
    Config-->>ingest: embed_mode, model path
    ingest->>Cache: Check if stores cached
    
    alt Stores not cached
        ingest->>Archive: Initialize
        ingest->>Vector: Initialize (with embed mode)
        ingest->>KG: Initialize
        ingest->>Cache: Cache stores
    end
    
    ingest->>ingest: Normalize transcript
    ingest->>Archive: Record turns
    ingest->>Vector: Add text with metadata
    ingest->>ingest: Update agent stats
    ingest-->>Client: Return {archived, agent, data_dir}
Loading
sequenceDiagram
    participant Client
    participant search as search()
    participant Cache as Store Cache
    participant Vector as VectorMemory
    participant KG as TemporalKnowledgeGraph
    participant Archive as ArchiveStore
    participant Formatter as Hit Formatter

    Client->>search: search(query, agent, limit, data_dir)
    search->>search: Resolve data directory
    search->>Cache: Get cached stores
    
    alt Stores not cached
        search->>Vector: Initialize
        search->>KG: Initialize
        search->>Archive: Initialize
        search->>Cache: Cache stores
    end
    
    par Parallel retrieval
        search->>Vector: Query vector memory
        search->>KG: Query knowledge graph
        search->>Archive: Query archive
    end
    
    search->>Formatter: Format raw hits
    Formatter->>Formatter: Extract confidence & timestamp
    Formatter-->>search: Formatted hits
    search-->>Client: Return list of {text, source, timestamp, confidence, metadata}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Hops with glee!
Transcripts now flow and ingested with care,
Search queries leap through the vector-ware,
Stores cache themselves with a whisker-twitch swift,
Config modes settle—this API's a gift! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding the taosmd.ingest() and search() functions as top-level API to implement the agent-rules contract.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/top-level-ingest-search-api

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@kilo-code-bot

kilo-code-bot Bot commented May 1, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • taosmd/__init__.py - 0 issues
  • taosmd/api.py - 0 issues
  • tests/test_api.py - 0 issues

Reviewed by grok-code-fast-1:optimized:free · 99,107 tokens

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/test_api.py (1)

40-47: 💤 Low value

Consider logging cleanup exceptions for debugging.

Static analysis flags the bare except Exception: pass pattern. While acceptable in test cleanup (you want tests to complete regardless), logging at debug level would aid troubleshooting if cleanup silently fails.

♻️ Optional improvement
             if store and hasattr(store, "close"):
                 try:
                     asyncio.run(store.close())
-                except Exception:
-                    pass
+                except Exception as exc:
+                    # Don't fail teardown, but log for debugging
+                    import logging
+                    logging.getLogger(__name__).debug("cleanup error: %s", exc)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_api.py` around lines 40 - 47, The cleanup loop in
tests/test_api.py silently swallows exceptions (bare except Exception: pass)
when calling store.close on entries from taosmd_api._stores_cache; change it to
capture the exception object and log it at debug level instead of passing
silently—import or use the test module logger (e.g.,
logging.getLogger(__name__)) and call logger.debug with a message that includes
the store identity and the exception (and optionally use logger.exception or
exc_info=True) when catching exceptions from store.close to aid debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/test_api.py`:
- Around line 40-47: The cleanup loop in tests/test_api.py silently swallows
exceptions (bare except Exception: pass) when calling store.close on entries
from taosmd_api._stores_cache; change it to capture the exception object and log
it at debug level instead of passing silently—import or use the test module
logger (e.g., logging.getLogger(__name__)) and call logger.debug with a message
that includes the store identity and the exception (and optionally use
logger.exception or exc_info=True) when catching exceptions from store.close to
aid debugging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7767886d-738b-4d1a-96ee-390eeafc4cad

📥 Commits

Reviewing files that changed from the base of the PR and between 1da60c4 and 9ed50fa.

📒 Files selected for processing (3)
  • taosmd/__init__.py
  • taosmd/api.py
  • tests/test_api.py

@jaylfc
jaylfc merged commit ec83f67 into master May 1, 2026
2 checks passed
@jaylfc
jaylfc deleted the fix/top-level-ingest-search-api branch May 1, 2026 00:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant