Using Letta with client-side tools DBs/RAG

Hi! I’m setting up Letta Typescript SDK in my React Native mobile app. For consumer privacy purposes, I have DBs/RAG on the local client-side (sql-lite, vector store, etc). And I have tools exposed to access such storage.

I was hoping to be able to NOT use storage or tools hosted on the Letta service itself, but mostly use it’s agentic and memory/context management strengths, but access tools on my client-side to interface with storage.

Is this not a use-case that is supported? I’m just getting started with Letta (played with and loved MemGPT maybe 2 years ago).

Kind regards, -Russ

1 Like

Hi Russ - interesting use case! I’ll explain the architecture constraints and potential approaches.

The Challenge

Letta tools execute server-side (where the agent runs), not client-side. This means tools run either on Letta Cloud or your self-hosted Letta server - they don’t execute in your React Native app’s JavaScript runtime.

From the docs:

“When running Letta locally, the tools are executed inside of the Docker container running the Letta service”

Potential Architectures

Option 1: Local Letta Server on Device

Run a self-hosted Letta server on the same mobile device:

  • Letta server runs as a background service
  • Tools access local SQLite/vector stores directly
  • React Native app connects via http://localhost:8283

Challenges:

  • Running Docker/Python on mobile is complex
  • Resource constraints (battery, memory)
  • Platform-specific (easier on Android than iOS)

Option 2: Callback Pattern (Recommended)

Run Letta server separately, but tools call back to your client:

// On React Native app - expose local API
const localServer = express();
localServer.post('/query-db', async (req, res) => {
  // Access local SQLite here
  const results = await localDB.query(req.body.sql);
  res.json(results);
});

// On Letta server - custom tool
def query_local_db(query: str) -> str:
    """Query the mobile device's local database"""
    import requests
    # Call back to the React Native app's local API
    response = requests.post(
        "http://mobile-device-ip:3000/query-db",
        json={"sql": query}
    )
    return response.json()

Benefits:

  • Letta handles agentic behavior and memory
  • Your client retains data control
  • Clear separation of concerns

Considerations:

  • Network latency for local calls
  • Need to handle device IP addressing
  • Security: authenticate callbacks

Option 3: Hybrid Memory Pattern

Use Letta for working memory, client-side for long-term storage:

// Client manages RAG/vector search locally
const searchResults = await localVectorDB.search(query);

// Send results to Letta as context
const response = await client.agents.messages.create({
  agent_id: agentId,
  messages: [{
    role: "user",
    content: `Context from local DB: ${searchResults}\n\nUser question: ${query}`
  }]
});

Benefits:

  • Simpler architecture
  • Letta focuses on reasoning and conversation management
  • Client handles all data access

For Your Privacy Requirements

The callback pattern (Option 2) or hybrid pattern (Option 3) best satisfy your privacy needs:

  • All data stays on device
  • Letta server only receives what you explicitly send
  • You control data flow completely

If you’re running self-hosted Letta on a local network (not Cloud), Option 2 gives you full control while still leveraging Letta’s agentic capabilities.

MCP Alternative

You could also explore creating an MCP server that runs alongside your React Native app and connects to Letta via stdio/SSE, though this adds complexity.

Does one of these architectures align with what you’re trying to build? Happy to elaborate on any approach.

Hey Russ - client-side tools are actually supported! It’s just not well documented yet, I’ll try to get to that today.

This pattern is used inside of Letta Code: GitHub - letta-ai/letta-code: A self-improving, stateful coding agent that can learn from experience and improve with use.

Basically - in Letta Code, the agent lives in the Letta service/server, but a subset of tools need to be executed locally on the client-side, like bash, grep , etc, because those only make sense inside of the client’s environment, not the server’s (like the agent cloud can’t meaningfully inspect the dev’s local filesystem, that needs to be done by the client itself).

Re: client-side storage, you could basically implement this by using Letta Code (or re-implementing the same client-side tool calling patterns) either via a custom local storage query tool (eg some node code that queries your local filesystem/DB), or just via client-side bash (like in Letta Code), where the agent can execute bash locally to access the local filesystem.

Does this make sense? Sorry about the lack of documentation here, will try and get it in ASAP.

Thanks for the response. From a high-level I think i see pattern you are thinking.

Letta code itself I imagine would be challenging to integrate inside of a React native app (it’s not technically node, so projects that have lots of dependencies on Node libraries/modules can be a challenge).

But I can feel the general approach you are describing seems possible. Not sure what kind of limitations as far as what functionality I’ll lose from Letta agents by having all storage/memory on client-side (accessible via tools).

I’ll start by seeing what my coding agents can come up with based on docs and your guidance. And will iterate.

1 Like

Put some docs up here! Client-side tool execution | Letta Docs

Not sure what kind of limitations as far as what functionality I’ll lose from Letta agents by having all storage/memory on client-side

TBH, I think the main “limitation” of client-side tools in Letta is that they’re more complex, in a similar way to HITL - the server is now waiting on the client, which means there’s an additional “step” in the agent loop. But once you understand the concept, I think it makes sense. Server-side tools = things that agent should be able to just call / use / chain together without any requests. Client-side tools + HITL = things that should block the agent execution in some way, and therefore require the client to “restart” execution.

1 Like

You rock! Thanks so much! :slight_smile: I’m quite impressed :slight_smile:

Using Letta-code as an example, I vibe coded the early first version of integrating client-side tools/storage with Letta API. Now I’m gonna use the new doc (that was lightning fast!!!) to really double click.

1 Like

Awesome, love to hear it!! Let us know if you have any other issues (sorry for the lag on reply here, still getting used to using discourse/forum vs discord)