Ratel Context Engineering Layer

repository·main·Indexed 42 days ago

https://github.com/ratel-ai/ratel

A context engineering layer for AI agents that reduces token costs and improves accuracy by preventing tool overload. Ratel indexes tools and skills into a catalog and uses progressive disclosure to inject only relevant capabilities into the context window. It features adaptive usage ranking via an IntentGraph to learn from agent invocations and provides SDKs for Python and TypeScript, including an adapter for the Vercel AI SDK.

Tokens
110.6K
Snippets
260
Records
443
Agent score
58%

What's inside Ratel

  1. Explore Ratel integration examples

    main

    Ratel provides several runnable demos that show how to wire Ratel into real agent frameworks and protocol surfaces. These examples are organized as private workspace packages and cover various integration patterns including adaptive ranking, Vercel AI SDK, Mastra, Pydantic AI, and OpenTelemetry.

    Available Integration Patterns

    Adaptive Ranking

    • TypeScript: adaptive-ranking-ts — Learn from invocations and persist/reload the graph.
    • Python: adaptive-ranking-python — The Python mirror of the TS version, including model-swap recovery.
    • Configurable (TS): configurable-adaptive-ranking-ts — Seed an intent graph from a baseline capture, then switch ranking on.
    • Configurable (Python): configurable-adaptive-ranking-python — The Python mirror for seeding.

    Agent Framework Integrations

    • Vercel AI SDK: ai-sdk — Demonstrates top-K filtering and capability tools within ToolLoopAgent.generate.
    • Mastra: mastra — Demonstrates capability tools and per-turn recall processors via @ratel-ai/mastra.
    • Pydantic AI (Python): pydantic-ai — Demonstrates top-K filtering and capability tools in the agent loop.
    • MCP Chat: mcp-chat — An interactive REPL against an MCP-backed agent using Vercel AI SDK and OpenAI.

    Telemetry

    • TypeScript: telemetry-ts — Emits ratel.* spans via the OpenTelemetry JS SDK.
    • Python: telemetry-python — Emits ratel.* spans via the OpenTelemetry Python SDK.
  2. How the Framework Adapter SPI works

    main

    Ratel provides a Service Provider Interface (SPI) to allow seamless integration with different AI frameworks (like Vercel AI SDK). This is achieved using the ratel(config).adaptTo(adapter) pattern.

    An adapter is composed of:

    1. Three required codecs: To handle data translation between Ratel and the host framework.
    2. Optional extension hooks: To provide additional functionality.
    3. Framework-specific idioms: To ensure the integration feels native to the host.

    To ensure correctness, community adapters should be validated against the @ratel-ai/sdk/testkit conformance testkit, which pins the required contract and uses framework-supplied hooks to verify the adapter.

    // Conceptual usage pattern
    ratel(config).adaptTo(adapter);
  3. Understand Adaptive Usage Ranking

    main

    Adaptive usage ranking is an online learning mechanism that sits on top of the existing retrieval fusion (BM25 and dense cosine). While standard rankers score based solely on text similarity, the adaptive ranker uses historical usage patterns to boost relevant tools.

    For example, if a query like "why is the build broken" consistently leads to the use of a gh_run_list tool, the adaptive ranker learns this relationship and boosts that tool's rank, even if other tools have higher lexical similarity to the word "build".

  4. Evaluate graph quality using coverage

    main

    When monitoring a seeded graph, do not rely solely on support or obs (observations). A healthy-looking graph can still fail if it doesn't generalize to your actual traffic.

    The Metric to Watch: coverage

    • Definition: The number of held-out queries (invented agent-style queries) that matched a cluster.
    • Why it matters: If coverage is low even while support is high, it means your graph is learning from the baseline but failing to generalize to the way users actually phrase questions (e.g., users describing a symptom while the agent searches by action).

    Other Metrics:

    • clusters: Distinct intents found so far.
    • support: Observations behind the cluster this turn landed in (scaled by how close it is to full strength).
    • obs: Total confirmed observations across every cluster.
    • from_baseline: Count of observations originating from the initial capture (stays constant after the 'flip' to live serving).
  5. Use searchable-description projections for tool, skill, and fact retrieval

    main

    To tune how tools, skills, and facts are retrieved (via BM25 or dense retrieval) without changing the descriptions or schemas seen by the LLM, you can use the experimental experimental_searchable_description field.

    When this field is provided, the retrieval engine uses a specific projection order instead of the default schema-inclusive projection. This allows catalog operators to optimize for recall and ranking independently of the model-facing payload.

    Projection Order for Opted-in Entries:

    1. name (both whole and identifier-split)
    2. The experimental_searchable_description override (verbatim)
    3. tags (whole and identifier-split, applicable to skills and facts)

    Key Behaviors:

    • Tool Isolation: For tools with an override, input and output schemas are used for the model but are not indexed for retrieval. Tools without an override continue to use the stable schema-inclusive projection.
    • Partial Override: The override only replaces the description component. name and tags are always indexed, even if the override is empty.
    • Cache Invalidation: Editing the experimental_searchable_description counts as catalog churn. The system uses a SHA-256 hash of the projected text to manage embedding caches; changing the override will invalidate the cached vector for that entry.
  6. Understand the implications of Adaptive Usage Ranking

    main

    Adaptive usage ranking introduces an online learning layer that adjusts retrieval results based on actual user choices (what users chose when the ranker was wrong). This provides a signal that goes beyond manual description-writing.

    Key behaviors to note:

    • Order-dependence: Ranking is no longer strictly deterministic. The same events in a different order can produce a different graph. To achieve reproducible results for CI, benchmarks, or bug reports, you must replay the JSONL trace log.
    • Persistence is the caller's responsibility: Ratel provides toJson and fromJson methods along with a monotonic rev (revision) field. You must implement the logic to save and detect stale bases (single-writer supported; no built-in merge).
    • Repair via Replay: If events are dropped from the stream, they are lost permanently. The repair path is to replay the ~/.ratel/telemetry log at construction.
    • Feedback Loops: Boosting used capabilities makes them more likely to be used. While W < 1 and support ramp bounds limit this, a feedback loop is inherent. Seeding from a trusted agent is recommended to provide a high-quality starting point.
    • Rebuilding is expensive: Rebuilding the graph is an $O(\text{whole log})$ operation. It should be used for bootstrapping or repairing, not as a per-turn serving operation.
  7. How to use conformance vectors in a new implementation

    main

    If you are building a new implementation (such as a managed cloud service, a Rust/TS/Python loader, or a new server), you do not need to run verify.mjs directly. Instead, you should consume the vectors.json file to validate your code path.

    An implementation is considered conformant when, for every etag vector, it:

    1. Resolves the fixture catalog for the specified scope.
    2. Produces the exact resolvedIds and etag committed in the vectors.
    3. Reproduces every inm (If-None-Match) outcome defined in the vectors.
  8. Manage graph persistence with rev-gating and stale-base detection

    main

    To efficiently manage state and prevent data loss, use the graph.rev property, which is a monotonic write counter.

    • Save-when-changed (rev-gating): Only persist the graph when graph.rev has changed since your last save to avoid unnecessary I/O.
    • Stale-base detection: Before overwriting a stored graph, compare its stored rev with the current one to ensure you aren't overwriting changes from a concurrent writer.

    Note: The supported model is single-writer.

  9. How to use conformance vectors in a custom implementation

    main

    If you are building a managed cloud service, a loader (in Rust, TS, or Python), or a future server, you do not need to run verify.mjs directly. Instead, your implementation is considered conformant if it can satisfy the requirements defined in vectors.json:

    1. For every etag vector, your implementation must resolve the fixture catalog for the specified scope and produce the exact resolvedIds and etag committed in the file.
    2. Your implementation must reproduce every inm (If-None-Match) outcome specified in the vectors.

    verify.mjs is intended as the tool to generate and validate these expectations, while your implementation should consume the data in vectors.json to verify its own logic.

  10. Understand how searchable-text projections work

    main

    The searchable_text projection determines which parts of a tool are indexed for retrieval. To prevent tool arguments from competing with the tool's actual purpose for ranking priority, the projection is restricted to specific semantic elements.

    Indexed elements:

    • Tool name: The identifier of the tool.
    • Tool description: The primary prose describing what the tool does.
    • Input-schema property names: The names of parameters (recursively including nested objects and array items). These are included because parameter names (e.g., branch) often contain semantic signal useful for matching queries.

    Excluded elements (not indexed):

    • Property descriptions: Prose intended to help a model fill an argument is excluded to prevent length imbalance.
    • Enum values: These are treated as data rather than semantic meaning.
    • Output schema: The shape of the returned data is not indexed, as it does not describe the caller's intent.

    Key takeaway for developers: If you want to improve tool retrieval, focus on the tool description. Writing richer documentation inside the parameter schema (property descriptions) will not change the retrieval/ranking behavior.

  11. Configure Fact pinning with the Pin enum

    main

    When defining facts, you can control their injection tier using the pin flag. This determines how the fact is treated by the freshness gate. New facts default to retrieved and must be deliberately promoted to always.

    • Pin.Always / Pin.ALWAYS: Pins the fact to the 'always-on' tier. This makes the content cache-friendly by keeping the transcript prefix stable across turns, improving prompt-cache hit rates.
    • retrieved (Default): Facts are retrieved as needed but not pinned to the constant grounding tier.

    Fact IDs must follow the pattern [A-Za-z0-9._:-]+ and are enforced at both the FactCatalog and FactRegistry levels.

    // Example of pinning a fact (conceptual usage)
    const myFact = {
      id: 'user_preference_1',
      content: 'User prefers dark mode',
      pin: Pin.Always
    };
  12. How Ratel protocol versioning works

    main

    Ratel follows a major-versioning strategy for its wire contracts:

    • Major Versions: Represented by subfolders (e.g., v1/, v2/). A bump in major version is a compatibility event for all sources and loaders.
    • Additive Changes: Within a stable major version, new optional fields, new endpoints, or new enum members are allowed. Conforming clients must ignore fields they do not recognize.
    • Breaking Changes: Any change that alters the meaning of an existing shape (including ETag content projection) requires a new major version.
    • Preview Versions: Versions in the experimental preview (like v2/) may change before they graduate to a stable release.