> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xysq.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# XysqAgent & Integrations

> Memory-aware agent wrapper with configurable context strategies, and tool-calling integrations for LiteLLM and Anthropic.

The SDK offers two ways to wire xysq memory into your LLM calls:

1. **`XysqAgent`** — a turn-based wrapper that handles memory retrieval and capture automatically on every `chat()` call
2. **Tool calling integrations** — expose xysq operations as LLM tools (function-calling), letting the model decide when to capture and recall

## XysqAgent

`XysqAgent` wraps any [LiteLLM](https://github.com/BerriAI/litellm)-compatible model. On every `chat()` call it:

1. Runs the configured context strategy to fetch relevant memories
2. Injects retrieved context into the system prompt
3. Calls the LLM
4. Optionally captures the exchange

Memory persists across instances — a fresh `XysqAgent` in a new session will have access to everything captured by previous sessions.

```bash theme={"dark"}
pip install 'xysq[agent]'
```

```python theme={"dark"}
from xysq import Xysq, XysqAgent

with Xysq() as client:
    agent = XysqAgent(
        client=client,
        model="gpt-4o-mini",        # any LiteLLM model string
        api_key="sk-...",
        system_prompt="You are a helpful coding assistant.",
        context_strategy="surface", # "surface" | "synthesize" | "both" | "none"
        surface_budget="low",       # "low" | "mid" | "high"
    )

    reply = agent.chat("I prefer functional programming over OOP.")
    print(reply)

    # Fresh agent — memory carries over automatically
    agent2 = XysqAgent(client=client, model="gpt-4o-mini", api_key="sk-...")
    reply = agent2.chat("What are my coding preferences?")
    print(reply)
```

### Context strategies

A context strategy controls what memory context is injected into each turn's system prompt.

| Strategy        | Behaviour                                                  |
| --------------- | ---------------------------------------------------------- |
| `"surface"`     | Retrieves raw memory items relevant to the current message |
| `"synthesize"`  | Runs a synthesis query and injects the answer              |
| `"both"`        | Runs both and injects both                                 |
| `"none"`        | No automatic context injection                             |
| Custom callable | Any object matching the `ContextStrategy` protocol         |

### Custom strategy

Implement the `ContextStrategy` protocol — any callable with this signature:

```python theme={"dark"}
def __call__(
    self,
    client,       # the Xysq sync client
    message: str, # current user message
    turn_count: int,
    history: list[dict[str, str]],
) -> str:         # context string to inject, or "" for none
    ...
```

**Example — adaptive strategy:**

```python theme={"dark"}
from xysq import ContextStrategy, Xysq, XysqAgent

class AdaptiveStrategy:
    """Synthesize on the first turn for a broad overview,
    then surface on follow-ups for precise recall."""

    def __init__(self, budget: str = "low") -> None:
        self.budget = budget

    def __call__(self, client, message, turn_count, history):
        if turn_count == 1:
            result = client.memory.synthesize(message, budget=self.budget)
            return f"[overview] {result.answer}" if result.answer else ""
        else:
            items = client.memory.surface(message, budget=self.budget)
            return "\n".join(f"- {m.text}" for m in items)

with Xysq() as client:
    agent = XysqAgent(
        client=client,
        model="gpt-4o-mini",
        api_key="sk-...",
        context_strategy=AdaptiveStrategy(budget="low"),
    )
    agent.chat("Summarise what you know about me.")
```

### XysqAgent parameters

| Parameter          | Type              | Default     | Description                                                               |
| ------------------ | ----------------- | ----------- | ------------------------------------------------------------------------- |
| `client`           | `Xysq`            | required    | Sync xysq client                                                          |
| `model`            | `str`             | required    | LiteLLM model string (e.g. `"gpt-4o-mini"`, `"claude-sonnet-4-20250514"`) |
| `api_key`          | `str`             | `None`      | LLM provider API key                                                      |
| `system_prompt`    | `str`             | default     | Base system prompt                                                        |
| `context_strategy` | `str \| callable` | `"surface"` | Context injection strategy                                                |
| `capture_strategy` | `str`             | `"auto"`    | `"auto"` \| `"manual"` \| `"both"` \| `"none"`                            |
| `surface_budget`   | `str`             | `"mid"`     | Budget for surface/synthesize calls                                       |
| `team_id`          | `str`             | `None`      | Scope memory operations to a team vault                                   |

***

## Tool calling integrations

Tool calling lets the LLM decide when to invoke memory operations — you pass the tool definitions to your LLM call, execute any tool calls the model returns, and feed results back.

### LiteLLM

```bash theme={"dark"}
pip install 'xysq[agent]'
```

```python theme={"dark"}
import litellm
from xysq import Xysq
from xysq.integrations.litellm import XysqLiteLLMTools

with Xysq() as client:
    tools = XysqLiteLLMTools(client)

    messages = [
        {
            "role": "system",
            "content": "You have persistent memory tools. Use them proactively.",
        },
        {
            "role": "user",
            "content": "I always want Python examples with type hints.",
        },
    ]

    # LLM decides which tools to call
    response = litellm.completion(
        model="gpt-4o-mini",
        messages=messages,
        tools=tools.definitions,
    )

    # Execute tool calls and collect results
    tool_calls = response.choices[0].message.tool_calls
    if tool_calls:
        results = tools.execute(tool_calls)
        messages.append(response.choices[0].message.model_dump(exclude_none=True))
        messages.extend(results)

        # Continue the conversation
        final = litellm.completion(model="gpt-4o-mini", messages=messages)
        print(final.choices[0].message.content)
```

### Anthropic

```bash theme={"dark"}
pip install 'xysq[claude]'
```

```python theme={"dark"}
import anthropic
from xysq import Xysq
from xysq.integrations.anthropic import XysqAnthropicTools

with Xysq() as client:
    tools = XysqAnthropicTools(client)

    claude = anthropic.Anthropic(api_key="sk-ant-...")
    response = claude.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        tools=tools.definitions,
        messages=[{"role": "user", "content": "What do you know about my preferences?"}],
    )

    # Execute tool_use blocks
    for block in response.content:
        if block.type == "tool_use":
            result = tools.execute([block])
```

### Available tools

Both integrations expose the same five tools to the LLM:

| Tool name            | Operation                  |
| -------------------- | -------------------------- |
| `xysq_capture`       | Store a memory             |
| `xysq_surface`       | Retrieve relevant memories |
| `xysq_synthesize`    | Ask a question from memory |
| `xysq_list_memories` | List recent memories       |
| `xysq_delete_memory` | Delete a memory by ID      |

To file an external source (link, quote, code snippet), the model calls `xysq_capture` with `source` tags, the same as any other memory.

***

## Examples

| File                                                                                                                   | What it demonstrates                                      |
| ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| [`02_chatbot_with_memory.py`](https://github.com/xysq-ai/sdk_python_xysq/blob/main/examples/02_chatbot_with_memory.py) | Multi-turn chatbot with LiteLLM and memory injection      |
| [`05_agent_with_tools.py`](https://github.com/xysq-ai/sdk_python_xysq/blob/main/examples/05_agent_with_tools.py)       | LLM-driven tool-calling loop                              |
| [`06_xysq_agent.py`](https://github.com/xysq-ai/sdk_python_xysq/blob/main/examples/06_xysq_agent.py)                   | XysqAgent with surface, synthesize, and custom strategies |

***

## Related

<CardGroup cols={2}>
  <Card title="Memory operations" icon="brain" href="/sdk/memory">
    Full reference for capture, surface, and synthesize
  </Card>

  <Card title="Team Vaults" icon="users" href="/sdk/teams">
    Scope agent memory to a shared team vault
  </Card>
</CardGroup>
