memra/sdk
Composer 安装命令:
composer require memra/sdk
包简介
Official PHP SDK for Memra - Memory API for AI agents
README 文档
README
Official PHP SDK for the Memra Memory API -- persistent, searchable memory for AI agents and LLM applications. Privacy-first and EU-native.
Since 4.5.0 the SDK version tracks the Memra platform version.
What's New in 4.5.0
- Read-your-writes: every write response includes a
revisiontoken; pass it torecall(waitForRevision:)to guarantee the write is indexed before recall runs. - Conflicts on write: create responses include
conflicts-- memories the new fact contradicts (when contradiction detection is enabled). - Token-budget recall:
recall(maxTokens:)trims results to fit a token budget. - Recall filters:
notTags,since,untilfor tag-exclusion and time-window recall. - Feedback loop: report which recalled memories were actually used via
memories()->feedback()or inline withrecall(usedIds:)-- boosts future scoring. - Entity graph API:
entities()->list()andentities()->memories()make the entity graph queryable. - Read-only scoped keys: the API now supports read-only scoped API keys -- use one with this SDK for recall-only integrations (write calls will be rejected by the server).
Requirements
- PHP 8.1+
- Guzzle 7.5+ (ships with Laravel)
Installation
composer require memra/sdk
Configuration (Laravel)
The SDK auto-discovers via Laravel's package discovery -- no manual registration needed.
Set your API key in .env:
MEMRA_API_KEY=memra_live_your_key_here MEMRA_PROJECT_ID=my-project
Optionally publish the config file:
php artisan vendor:publish --tag=memra-config
This creates config/memra-sdk.php where you can customize base_url, timeout, and project_id.
Using
config:cache? Publishing the config file is recommended -- it guarantees the SDK's settings are part of your cached configuration. Remember to re-runphp artisan config:cacheafter installing or updating the SDK.
Quick Start (Laravel) -- 5 Minutes
1. Install
composer require memra/sdk
2. Configure
Add to your .env:
MEMRA_API_KEY=memra_live_your_key_here MEMRA_PROJECT_ID=my-project
3. Store a Memory
use Memra\Sdk\Facades\Memra; $memory = Memra::add( content: 'User prefers dark mode and TypeScript', tenantId: 'user_123', projectId: 'my-project', type: 'preference', importance: 8, tags: ['ui', 'language'], ); echo $memory->id; // mem_01HXYZ...
4. Recall Memories
$results = Memra::recall( query: 'What does the user prefer?', tenantId: 'user_123', projectId: 'my-project', limit: 5, ); foreach ($results->data as $memory) { echo "{$memory->content} (score: {$memory->score})\n"; }
5. Delete a Memory
Memra::delete('mem_01HXYZ');
Quick Start (Plain PHP)
use Memra\Sdk\MemraClient; $client = new MemraClient(apiKey: 'memra_live_your_key_here'); // Store a memory $memory = $client->memories()->add( content: 'User prefers dark mode', tenantId: 'user_123', projectId: 'my-project', type: 'preference', importance: 8, ); // Recall memories $results = $client->memories()->recall( query: 'What does the user prefer?', tenantId: 'user_123', projectId: 'my-project', ); // List memories $list = $client->memories()->list( tenantId: 'user_123', projectId: 'my-project', ); // Delete a memory $client->memories()->delete($memory->id);
API Reference
Memories
// Via Facade (Laravel) Memra::add(content, tenantId, projectId, type?, importance?, tags?, source?, metadata?); Memra::recall(query, tenantId, projectId, limit?, types?, tags?, minImportance?, minScore?, includeRecency?, rerank?, waitForRevision?, maxTokens?, notTags?, since?, until?, usedIds?); Memra::list(tenantId, projectId, type?, tags?, minImportance?, limit?, offset?); Memra::delete(id); // Via Client (Plain PHP or Laravel) $client->memories()->add(...); $client->memories()->recall(...); $client->memories()->list(...); $client->memories()->get(id); $client->memories()->update(id, content?, importance?, tags?, metadata?); $client->memories()->delete(id); $client->memories()->bulkDelete(tenantId, projectId?); $client->memories()->batch(memories); // Up to 100 per call $client->memories()->supersede(id, content, metadata?); $client->memories()->chain(id); // Get supersession chain $client->memories()->promote(id, targetNamespace?, promotedBy?); // -> PromotionResult $client->memories()->refresh(id); // Reset staleness -> HealthStatus $client->memories()->feedback(tenantId, projectId, memoryIds); // -> ['updated' => int]
Write responses (v4.5)
Every write returns a Memory DTO with:
revision(int) -- read-your-writes token; pass torecall(waitForRevision:)embeddingStatus(string) -- embeddings are async:'pending'until indexedconflicts(array) -- on create, memories the new fact contradicts (empty unless contradiction detection is enabled)
$memory = $client->memories()->add( content: 'User switched to PostgreSQL', tenantId: 'user_123', projectId: 'my-project', ); // Read-your-writes: this recall is guaranteed to see the write above $results = $client->memories()->recall( query: 'What database does the user run?', tenantId: 'user_123', projectId: 'my-project', waitForRevision: $memory->revision, );
Recall options (v4.5)
$results = $client->memories()->recall( query: 'deployment preferences', tenantId: 'user_123', projectId: 'my-project', maxTokens: 2000, // token-budget recall notTags: ['archived'], // exclude by tag since: '2026-01-01T00:00:00Z', // time window until: '2026-06-30T23:59:59Z', usedIds: ['mem_01ABC'], // feedback from previous recall );
Feedback loop (v4.5)
Report which recalled memories were actually useful -- they get a scoring boost on future recalls:
$result = $client->memories()->feedback( tenantId: 'user_123', projectId: 'my-project', memoryIds: ['mem_01ABC', 'mem_02DEF'], ); echo $result['updated']; // 2
Or save a round trip by passing usedIds on the next recall() call.
Projects
$client->projects()->create(name, description?); $client->projects()->list(limit?, offset?); $client->projects()->get(id); $client->projects()->delete(id);
Webhooks
$client->webhooks()->create(url, events, secret?); $client->webhooks()->list(); $client->webhooks()->delete(id);
Bootstrap
$client->bootstrap()->get(agentId, tenantId?, projectId?, maxTokens?, includeTypes?, excludeTypes?, recencyDays?); $client->bootstrap()->configure(agentId, config); $client->bootstrap()->showConfig(agentId);
Health
$client->health()->memory(id); // Single memory health status $client->health()->refresh(id, note?); // Reset staleness score $client->health()->namespace(tenantId?, projectId?); // Namespace-level health
Audit
$client->audit()->list(filters?); $client->audit()->export(format?, filters?); // CSV or JSON
Erasure
$client->erasure()->create(tenantId, reason?); // Erasure request $client->erasure()->show(id);
Export
$client->export()->account(format?); // Full account export $client->export()->namespace(tenantId, projectId?, format?);
Entities (v4.5)
Query the entity graph built by the intelligence pipeline:
// List entities for a namespace (most-mentioned first) $entities = $client->entities()->list( tenantId: 'user_123', projectId: 'my-project', entityType: 'person', // optional filter limit: 50, // optional (max 200) ); foreach ($entities as $entity) { echo "{$entity->name} ({$entity->type}): {$entity->memoryCount} memories\n"; } // List memories mentioning an entity (metadata only, no content) $result = $client->entities()->memories( name: 'Jane Doe', tenantId: 'user_123', projectId: 'my-project', ); // $result = ['entity' => 'Jane Doe', 'memories' => [...], 'total' => 3]
PII entities appear under their stable IDs, never raw values.
Usage
$client->usage()->get();
Privacy & Data Protection
Memra is privacy-first. The PHP SDK provides access to data export and erasure endpoints.
Data Export
// Export all account data $data = $client->export()->account(); echo $data->exported_at; // Export namespace data (per-tenant) $data = $client->export()->namespace('tenant_123'); // Export namespace data filtered by project $data = $client->export()->namespace('tenant_123', projectId: 'proj_1');
Data Erasure
// Request erasure of a memory $request = $client->erasure()->create('mem_abc123'); echo $request->status; // 'pending' // Check erasure status $status = $client->erasure()->show('mem_abc123'); echo $status->status; // 'completed'
Erasure is thorough: flat files, database index rows, Redis cache entries, and audit log entries are all purged. The erasure request is tracked with a scheduled deletion date and completion status.
Memory Types
| Type | Description |
|---|---|
fact |
Factual knowledge (e.g., "User works at Acme Corp") |
event |
Time-bound occurrences (e.g., "User deployed v2.0 on March 15") |
pattern |
Behavioral patterns (e.g., "User always reviews PRs before merging") |
working |
Short-term context, auto-expires after 24 hours |
decision |
Decisions with supersession chains (e.g., "Switched from MySQL to PostgreSQL") |
preference |
User preferences (e.g., "Prefers dark mode") |
context |
Contextual information (e.g., "Currently working on Project X") |
entity |
Entity references (e.g., "User's manager is Jane Doe") |
Error Handling
All API errors throw typed exceptions:
use Memra\Sdk\Exceptions\MemraAuthException; use Memra\Sdk\Exceptions\MemraNotFoundException; use Memra\Sdk\Exceptions\MemraValidationException; use Memra\Sdk\Exceptions\MemraQuotaException; use Memra\Sdk\Exceptions\MemraServerException; use Memra\Sdk\Exceptions\MemraTimeoutException; try { $memory = Memra::add( content: 'Important fact', tenantId: 'user_123', projectId: 'my-project', ); } catch (MemraAuthException $e) { // 401 -- invalid or missing API key echo "Auth error: {$e->getMessage()}"; } catch (MemraValidationException $e) { // 422 -- validation errors with per-field details foreach ($e->errors as $field => $messages) { echo "{$field}: " . implode(', ', $messages) . "\n"; } } catch (MemraQuotaException $e) { // 429 -- rate limited echo "Rate limited. Retry after {$e->retryAfter} seconds."; echo "Remaining: {$e->remaining}"; } catch (MemraNotFoundException $e) { // 404 -- resource not found echo "Not found: {$e->getMessage()}"; } catch (MemraServerException $e) { // 500/502/503 -- server error echo "Server error ({$e->statusCode}): {$e->getMessage()}"; } catch (MemraTimeoutException $e) { // Connection timeout echo "Request timed out: {$e->getMessage()}"; }
All exceptions extend MemraException and include statusCode and responseBody properties.
Testing
Use Memra::fake() in your tests to avoid making real API calls:
use Memra\Sdk\Facades\Memra; test('it stores a user preference', function () { $fake = Memra::fake(); // Your application code that calls Memra::add() storeUserPreference('user_123', 'dark mode'); // Assert the memory was stored $fake->assertAdded(); // Assert with specific criteria $fake->assertAdded(fn (array $args) => $args['content'] === 'User prefers dark mode' && $args['type'] === 'preference' ); }); test('it recalls memories during conversation', function () { $fake = Memra::fake(); getRelevantContext('user_123', 'What do I prefer?'); $fake->assertRecalled(); }); test('it handles empty state', function () { $fake = Memra::fake(); // Nothing should happen in this test path $fake->assertNothingSent(); });
Available Assertions
| Method | Description |
|---|---|
$fake->assertAdded(?callable) |
Assert add() was called, optionally matching a callback |
$fake->assertRecalled(?callable) |
Assert recall() was called, optionally matching a callback |
$fake->assertDeleted(?string $id) |
Assert delete() was called, optionally for a specific ID |
$fake->assertNothingSent() |
Assert no calls were made |
License
MIT License. See LICENSE for details.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-04