diff --git a/content/Guides/agent-communication.mdx b/content/Guides/agent-communication.mdx
index 072521ed..186dafad 100644
--- a/content/Guides/agent-communication.mdx
+++ b/content/Guides/agent-communication.mdx
@@ -5,17 +5,15 @@ description: Agent-to-Agent communication patterns, usage and best practices
import Image from "next/image";
-
+
-### How do agents communicate with each other?
+## Overview
-In most advanced agentic scenarios, agents need to communicate with other agents to achieve their goals.
-
-In fact, our recommendation is that you build agents with highly specialized roles and skills and use agent-to-agent communication to achieve the overall goal.
+In most advanced agentic scenarios, agents need to communicate with other agents to achieve their goals. In fact, our recommendation is that you build agents with highly specialized roles and skills and use agent-to-agent communication to achieve the overall goal.
There are a number of ways to achieve agent-to-agent communication natively in Agentuity.
-#### Communication Types
+## Communication Types
Agents can communicate with each other in a number of ways in the Agentuity platform. The following are the different types of communication that are supported:
@@ -25,28 +23,28 @@ Agents can communicate with each other in a number of ways in the Agentuity plat
| **Inter Project** | Agents can communicate with each other across projects within the same organization across the internal network |
| **Inter Organization** | Agents can communicate with each other across organizations across the internal network |
-##### Intra Project
+### Intra Project
Intra project communication is the simplest form of agent-to-agent communication. Agents within the same project can communicate with each other locally without leaving the local network.
-##### Inter Project
+### Inter Project
Inter project communication is a more advanced form of agent-to-agent communication. Agents can communicate with each other across projects within the same organization but will communicate over the internal network.
-##### Inter Organization
+### Inter Organization
Inter organization communication is the most advanced form of agent-to-agent communication. Agents can communicate with each other across organizations. Currently, Agentuity only supports inter organization agent communication if the target agent is public and the source agent has been given the agent ID by the other organization. For inter organization communication, the source agent will communicate over the internal network.
-#### Communication Methods
+## Communication Methods
-Agents has two primary methods of communication with other agents:
+Agents have two primary methods of communication with other agents:
| Type | Description |
|-----------|-------------|
| Handoff | Agents can handoff a request to another agent to complete |
| Invocation | Agents can invoke another agent to complete a task and wait for the result |
-##### Handoff
+### Handoff
When an agent needs to handoff a request to another agent, it can do so by using the SDK `handoff` method. The `handoff` method will send the request to another agent and the other agent will be responsible for completing the request.
@@ -81,20 +79,24 @@ export default async function Agent(
resp: AgentResponse,
ctx: AgentContext
) {
- return resp.handoff({name: 'My Other Agent'}, "would you please do this?");
+ return resp.handoff(
+ {name: 'My Other Agent'},
+ { data: "would you please do this?", contentType: "text/plain" }
+ );
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext
async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
+ # Python infers: string → text/plain, dict → application/json
return response.handoff({"name":"My Other Agent"}, "would you please do this?")
`} />
-##### Invocation
+### Invocation
-When an agent needs to invoke another agent to complete a task and wants to wait for the result, it can do so by using the SDK `getAgents` method on `AgentContext`. The `getAgents` will perform resolution to determine the target agent location and return a handle to the target agent that can be used to `run` the target agent.
+When an agent needs to invoke another agent to complete a task and wants to wait for the result, it can do so by using the SDK `getAgent` method on `AgentContext`. The `getAgent` will perform resolution to determine the target agent location and return a handle to the target agent that can be used to `run` the target agent.
-If the target agent is local (intra project), the `getAgents` method will return a handle to an internal agent which can be used to `run` the target agent.
+If the target agent is local (intra project), the `getAgent` method will return a handle to an internal agent which can be used to `run` the target agent.
-If the target agent is remote (inter project or inter organization), the `getAgents` method will return a handle to an external agent which can be used to `run` the target agent. In addition, the SDK internally will use the authorization token to authenticate the source agent to the target agent.
+If the target agent is remote (inter project or inter organization), the `getAgent` method will return a handle to an external agent which can be used to `run` the target agent. In addition, the SDK internally will use the authorization token to authenticate the source agent to the target agent.
+> **Note:** JavaScript uses `{ data, contentType }` format while Python infers content type from the raw payload passed directly.
+
In this trivial example above, the functionality is similar to the handoff example above. The source agent is sending a request to the `My Other Agent` agent and passing a message to the other agent. The `My Other Agent` agent will receive the request, perform an operation and return the result to the source agent. The source agent will simply return the result as a text result.
In a real life scenario, you'll likely want to pass the appropriate data types to the target agent and wait for the result and then use the result in your own agent to perform additional tasks.
-###### Parallel Execution
+#### Parallel Execution
Sometimes you want to send a request to multiple agents at the same time. This is an example of parallel execution.
@@ -144,22 +154,28 @@ export default async function Agent(
) {
const agent1 = await ctx.getAgent({name: 'My First Agent'});
const agent2 = await ctx.getAgent({name: 'My Second Agent'});
+ // Basic usage - perfect for simple object data
await Promise.all([
- agent1.run({task: 'My First Task'}),
- agent2.run({task: 'My Second Task'}),
+ agent1.run({ data: { task: 'My First Task' } }),
+ agent2.run({ data: { task: 'My Second Task' } }),
]);
+ // Explicit control when needed:
+ // await Promise.all([
+ // agent1.run({ data: { task: 'My First Task' }, contentType: 'application/json' }),
+ // agent2.run({ data: { task: 'My Second Task' }, contentType: 'application/json' }),
+ // ]);
return resp.text('OK');
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext
import asyncio
async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
- agent1 = await context.getAgent({"name":"My First Agent"})
- agent2 = await context.getAgent({"name":"My Second Agent"})
+ agent1 = await context.get_agent({"name":"My First Agent"})
+ agent2 = await context.get_agent({"name":"My Second Agent"})
await asyncio.gather(
- agent1.run({"task":"My First Task"}),
- agent2.run({"task":"My Second Task"}),
+ agent1.run({"task": "My First Task"}), # content type inferred as JSON
+ agent2.run({"task": "My Second Task"}), # content type inferred as JSON
)
return response.text('OK')
@@ -175,15 +191,15 @@ sequenceDiagram
actor Agentuity
actor Agent 2
actor Agent 3
- Agent 1-->>Agentuity: Get Agent 1
Agent 1-->>Agentuity: Get Agent 2
+ Agent 1-->>Agentuity: Get Agent 3
Agent 1->>Agent 2: Run
Agent 1->>Agent 3: Run
"/>
-#### Agent Resolution
+## Agent Resolution
-How do we resolve the target agent? There are two main ways to do this:
+How do we resolve the target agent? There are three main ways to do this:
| Type | Description |
|-----------|-------------|
@@ -191,11 +207,11 @@ How do we resolve the target agent? There are two main ways to do this:
| Agent Name | The agent name is a human readable name for an agent. It is a string that was used for the agent's name. |
| Project ID | The agent project ID is specified to disambiguate agents with the same name in different projects. |
-##### Intra Project Resolution
+### Intra Project Resolution
When calling an agent within the same project, the agent name is usually the easiest way to resolve the target agent. The agent name is a human readable name for an agent. It is a string that was used for the agent's name.
-##### Inter Project Resolution
+### Inter Project Resolution
When calling an agent across projects within the same organization, the agent ID is typically the most reliable way to resolve the target agent. The agent ID is a unique identifier for an agent.
@@ -211,23 +227,23 @@ export default async function Agent(
ctx: AgentContext
) {
return resp.handoff({
- id: 'agent_123456789abcedef',
- projectId: 'project_123456789abcedef',
+ id: 'agent-123456789abcedef',
+ projectId: 'project-123456789abcedef',
});
}`} py={`
from agentuity import AgentRequest, AgentResponse, AgentContext
async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
return response.handoff({
- "id": "agent_123456789abcedef",
- "projectId": "project_123456789abcedef"
+ "id": "agent-123456789abcedef",
+ "projectId": "project-123456789abcedef"
})
`} />
-##### Inter Organization Resolution
+### Inter Organization Resolution
Currently, Agentuity only supports inter organization agent communication if the target agent is public and the source agent has been given the agent ID by the other organization. When using inter organization communication, only the agent ID is required to resolve the target agent.
-#### Communication Authorization
+## Communication Authorization
When communicating with other agents outside the local project, Agentuity will automatically generate a one-time use authorization token with a short expiration. This token is used to authenticate the source agent to the target agent automatically without the need for the source agent to pass the token to the target agent.
diff --git a/content/Guides/agent-data-handling.mdx b/content/Guides/agent-data-handling.mdx
index 6a1f49a7..de491e2f 100644
--- a/content/Guides/agent-data-handling.mdx
+++ b/content/Guides/agent-data-handling.mdx
@@ -3,7 +3,9 @@ title: Agent Data Handling
description: How to handle data formats in your agents
---
-We provide a few different ways to handle data formats in your agents to make it easier to work with different data types. Of course, your agent can always perform its own data handling by use the raw data and the content type property. However, most common data types are supported out of the box.
+## Overview
+
+We provide a few different ways to handle data formats in your agents to make it easier to work with different data types. Of course, your agent can always perform its own data handling by using the raw data and the content type property. However, most common data types are supported out of the box.
## How it works
@@ -37,16 +39,16 @@ export default async function Agent(
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext
async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
- contentType = request.data.contentType
- if contentType == 'text/plain':
- text = await request.data.text()
- # do something with the text
- elif contentType == 'application/json':
- json = await request.data.json()
- # do something with the json
- else:
- # do something with the data
- pass
+ contentType = request.data.contentType
+ if contentType == 'text/plain':
+ text = await request.data.text()
+ # do something with the text
+ elif contentType == 'application/json':
+ json = await request.data.json()
+ # do something with the json
+ else:
+ # do something with the data
+ pass
`} />
## Request Data Formats
@@ -55,7 +57,7 @@ The following request data formats are supported out of the box:
### Text
-You use use the `text` method on the `Data` object to get the raw text data.
+You can use the `text` method on the `Data` object to get the raw text data.
+**Language Differences:** JavaScript supports structured data objects directly, while Python uses the standard `logging.Logger` interface (with structured data via `extra` parameters).
+
+
### 1. Use Appropriate Log Levels
+try:
+ # Operation that might fail
+ data = fetch_some_data()
+except Exception as err:
+ error_msg = str(err)
+ context.logger.error(f"Failed to fetch data error={error_msg}")`} />
+
+### 2. Use Structured Data
+
+Use structured data to provide context and make logs easier to parse and analyze:
+
+
+
+### 3. Include Relevant Context
Log enough information to understand what happened without re-running:
-### 3. Log Decision Points
+### 4. Include Agentuity-Specific Information
+
+Add Agentuity-specific information to help with debugging and monitoring:
+
+
+
+### 5. Log Decision Points
Help future debugging by logging key decisions:
+ key = "user_123"
+ reason = "expired"
+ context.logger.info(f"Cache miss, fetching fresh data cache_key={key} reason={reason}")
+`} />
-### 4. Avoid Logging Sensitive Data
+### 6. Avoid Logging Sensitive Data
Never log passwords, tokens, or personal information:
-
-### 5. Use Child Loggers for Request Context
-
-Create child loggers to automatically include context in all related logs:
-
-
-
-## Structured Logging
-
-Use structured data for easier parsing and analysis:
-
-
+user_id = "user123"
+context.logger.info(f"User authenticated user_id={user_id}")
+
+# Not this - Never log passwords!
+login_name = "john"
+user_password = "secret123"
+context.logger.info(f"Login attempt username={login_name} password={user_password}") # Never do this!
+`} />
+
+### 7. Use Child Loggers for Different Tasks
+
+Create child loggers to organize logging for different parts of your workflow:
+
+
For more observability features, see [Agent Telemetry](/Guides/agent-telemetry) and [Agent Tracing](/Guides/agent-tracing).
\ No newline at end of file
diff --git a/content/Guides/agent-streaming.mdx b/content/Guides/agent-streaming.mdx
index f37c688b..9c6eeea5 100644
--- a/content/Guides/agent-streaming.mdx
+++ b/content/Guides/agent-streaming.mdx
@@ -26,7 +26,7 @@ description: How to use streaming in your agents
└────────────────────────────────────────────────────────────────────────────────────────────┘
```
-#### Real-World Use Cases
+### Real-World Use Cases
- **Live chat / customer support.** Stream the assistant's words as they are generated for a more natural feel.
- **Speech-to-text.** Pipe microphone audio into a transcription agent and forward captions to the UI in real time.
@@ -70,7 +70,7 @@ async def run(request: AgentRequest, response: AgentResponse, context: AgentCont
chat_completion = client.chat.completions.create(
messages=[
{"role": "system", "content": "You are a friendly assistant!"},
- {"role": "user", "content": request.data.text or "Why is the sky blue?"},
+ {"role": "user", "content": (await request.data.text()) or "Why is the sky blue?"},
],
model="gpt-4o",
stream=True,
diff --git a/content/Guides/agent-tracing.mdx b/content/Guides/agent-tracing.mdx
index 111f342e..88cc7074 100644
--- a/content/Guides/agent-tracing.mdx
+++ b/content/Guides/agent-tracing.mdx
@@ -3,6 +3,8 @@ title: Agent Tracing
description: Understanding how to use tracing in your agents
---
+## Overview
+
Agent tracing provides deep visibility into your agent's execution flow, performance, and behavior using OpenTelemetry. This enables debugging, performance monitoring, and understanding complex agent workflows.
**Key benefits:**
@@ -96,7 +98,7 @@ import { SpanStatusCode } from '@opentelemetry/api';
const handler: AgentHandler = async (request, response, context) => {
return context.tracer.startActiveSpan('agent-request', async (parentSpan) => {
try {
- parentSpan.setAttribute('trigger', request.trigger());
+ parentSpan.setAttribute('trigger', request.trigger);
const data = await request.data.json();
// Create child span for data processing
diff --git a/content/Guides/ai-gateway.mdx b/content/Guides/ai-gateway.mdx
index 5e51106d..614bafad 100644
--- a/content/Guides/ai-gateway.mdx
+++ b/content/Guides/ai-gateway.mdx
@@ -1,6 +1,6 @@
---
title: Using AI Gateway
-description: Using AI Gateway in your Agents
+description: Using the AI Gateway in your Agents
---
## What is the AI Gateway?
diff --git a/content/Guides/key-value.mdx b/content/Guides/key-value.mdx
index 2e293507..ed8ea58d 100644
--- a/content/Guides/key-value.mdx
+++ b/content/Guides/key-value.mdx
@@ -38,14 +38,14 @@ Both JavaScript and Python SDKs automatically create key-value storage when you
{
- // Storage is created automatically on first use
- await context.kv.set('user-sessions', 'user-123', {
+const handler: AgentHandler = async (req, resp, ctx) => {
+ // Buckets are auto-created if they don't exist
+ await ctx.kv.set('user-sessions', 'user-123', {
lastSeen: new Date().toISOString(),
preferences: { theme: 'dark' }
});
- return response.json({ message: 'Session stored' });
+ return resp.json({ message: 'Session stored' });
};
export default handler;`} py={`# Python
@@ -66,46 +66,59 @@ async def run(request: AgentRequest, response: AgentResponse, context: AgentCont
The key-value API provides three core operations: `get`, `set`, and `delete`. All operations are asynchronous and support various data types.
+The first parameter in all operations is the storage bucket name (also called "name" or "namespace"). Buckets are automatically created when you first use them.
+
### Storing Data
-Store strings, objects, or binary data with optional TTL (time-to-live):
+Store strings, objects, or binary data. Keys persist indefinitely by default, or you can set a TTL (time-to-live) for automatic expiration:
-
+# Store feature flags (no TTL - persistent config)
+await context.kv.set("feature-flags", "beta-features", {
+ "darkMode": True,
+ "aiAssistant": False,
+ "newDashboard": True
+})`} />
### Retrieving Data
Retrieve stored values with automatic deserialization:
Remove keys when they're no longer needed:
@@ -155,13 +168,13 @@ Use hierarchical, descriptive keys to organize your data:
Always handle potential storage errors gracefully:
{
// Bucket is created automatically on first use
const imageData = Buffer.from(await request.data.binary());
- await context.objectstore.put('user-uploads', 'profile-123.jpg', imageData, {
- contentType: 'image/jpeg'
- });
+ // Auto-detect content type (simplest approach)
+ await context.objectstore.put('user-uploads', 'profile-123.jpg', imageData)
return response.json({ message: 'Image uploaded successfully' });
};
@@ -57,9 +56,8 @@ async def run(request: AgentRequest, response: AgentResponse, context: AgentCont
# Bucket is created automatically on first use
image_data = await request.data.binary()
- await context.objectstore.put("user-uploads", "profile-123.jpg", image_data, {
- "content_type": "image/jpeg"
- })
+ # Auto-detect content type (simplest approach)
+ await context.objectstore.put("user-uploads", "profile-123.jpg", image_data)
return response.json({"message": "Image uploaded successfully"})
`} />
@@ -70,7 +68,10 @@ The object storage API provides four core operations: `get`, `put`, `delete`, an
### Storing Objects
-Store files with automatic content type detection or explicit metadata:
+Object storage supports two approaches for storing files:
+
+1. **Automatic content type detection** (recommended for most cases) - The SDK detects the content type from the data
+2. **Explicit parameters** - Specify content type, metadata, and other options manually
+# Text file with encoding
+params = ObjectStorePutParams(
+ content_type="text/plain",
+ content_encoding="utf-8"
+)
+await context.objectstore.put("logs", "agent.log", log_content, params)`} />
### Retrieving Objects
@@ -257,6 +268,9 @@ await context.objectstore.put('uploads', filename, data, {
contentType
});`} py={`import os
+# Auto-detect or use explicit params
+from agentuity.server.objectstore import ObjectStorePutParams
+
content_types = {
".jpg": "image/jpeg",
".png": "image/png",
@@ -268,9 +282,8 @@ content_types = {
extension = os.path.splitext(filename)[1]
content_type = content_types.get(extension, "application/octet-stream")
-await context.objectstore.put("uploads", filename, data, {
- "contentType": content_type
-})`} />
+params = ObjectStorePutParams(content_type=content_type)
+await context.objectstore.put("uploads", filename, data, params)`} />
### Public URL Security
@@ -360,13 +373,17 @@ Create a robust file upload handler:
file_data = await request.data.binary()
key = f"uploads/{int(time.time())}-{file_name}"
- await context.objectstore.put("user-files", key, file_data, {
- "content_type": content_type,
- "metadata": {
+ # Using explicit params for metadata
+ from agentuity.server.objectstore import ObjectStorePutParams
+
+ params = ObjectStorePutParams(
+ content_type=content_type,
+ metadata={
"original-name": file_name,
"upload-time": datetime.now().isoformat()
}
- })
+ )
+ await context.objectstore.put("user-files", key, file_data, params)
# Generate access URL
url = await context.objectstore.create_public_url(
diff --git a/content/Guides/vector-db.mdx b/content/Guides/vector-db.mdx
index 900be0d4..4ff49d1f 100644
--- a/content/Guides/vector-db.mdx
+++ b/content/Guides/vector-db.mdx
@@ -3,8 +3,16 @@ title: Using Vector DB
description: Using the Vector DB for search and retrieval
---
+## When to Use Vector Storage
+
Vector storage enables semantic search for your agents, allowing them to find information by meaning rather than keywords. Ideal for knowledge bases, RAG systems, and persistent agent memory.
+Choose the right storage for your use case:
+
+- **Vector Storage**: Semantic search, embeddings, similarity matching
+- **[Key-Value Storage](/Cloud/key-value-memory)**: Fast lookups, simple data, temporary state
+- **[Object Storage](/Cloud/object-storage)**: Large files, media, backups
+
## Understanding Vector Storage
Vector storage works by converting text into high-dimensional numerical representations (embeddings) that capture semantic meaning. When you search, the system finds documents with similar meanings rather than just keyword matches.
@@ -58,9 +66,7 @@ The `upsert` operation inserts new documents or updates existing ones. You can p
**Idempotent Behavior:**
The upsert operation is idempotent - upserting with an existing key updates the existing vector rather than creating a duplicate. The same internal vector ID is reused, ensuring your vector storage remains clean and efficient.
-
-```javascript
-// JavaScript/TypeScript
+
+ids = await context.vector.upsert("custom-embeddings", embedding_docs)`} />
### Searching Vector Storage
Search operations find semantically similar documents based on a text query. You can control the number of results, similarity threshold, and filter by metadata.
-
-```javascript
-// JavaScript/TypeScript
+ {
- console.log(`Found: ${result.metadata.source}`);
- console.log(`Similarity: ${result.similarity}`);
-});
-```
-
-```python
-# Python
+ console.log(\`Found: \${result.metadata.source}\`);
+ console.log(\`Similarity: \${result.similarity}\`);
+});`} py={`# Python
# Semantic search with parameters
results = await context.vector.search(
"knowledge-base",
@@ -154,9 +148,7 @@ results = await context.vector.search(
# Process results
for result in results:
print(f"Found: {result.metadata['source']}")
- print(f"Similarity: {result.similarity}")
-```
-
+ print(f"Similarity: {result.similarity}")`} />
**Search Parameters:**
- `query` (required): Text query to search for
@@ -168,33 +160,108 @@ for result in results:
- **Both SDKs**: Return results with `similarity` field (1.0 = perfect match, 0.0 = no match)
- **Note**: The JavaScript SDK also returns a `distance` field for backward compatibility; prefer `similarity`
+### Retrieving Vectors by Key
+
+The `get` method retrieves a specific vector directly using its key, without performing a similarity search.
+
+
+
+**When to use `get` vs `search`:**
+- Use `get` when you know the exact key (like a database primary key lookup)
+- Use `search` when finding vectors by semantic similarity
+- `get` is faster for single lookups since it doesn't compute similarities
+- `get` returns `null` (JS) / `None` (Python) if the key is not found, but may throw errors for other failures
+
### Deleting Vectors
Remove specific vectors from storage using their keys.
-
-```javascript
-// JavaScript/TypeScript
+
+# For bulk operations, call delete multiple times`} />
## Practical Examples
diff --git a/content/SDKs/javascript/api-reference.mdx b/content/SDKs/javascript/api-reference.mdx
index 20b96e56..7c599c7f 100644
--- a/content/SDKs/javascript/api-reference.mdx
+++ b/content/SDKs/javascript/api-reference.mdx
@@ -270,6 +270,36 @@ for (const result of results) {
}
```
+#### get
+
+`get(name: string, key: string): Promise`
+
+Retrieves a specific vector from the vector storage using its key.
+
+**Parameters**
+
+- `name`: The name of the vector storage
+- `key`: The unique key of the vector to retrieve
+
+**Return Value**
+
+Returns a Promise that resolves to a `VectorSearchResult` object if found, or `null` if the key doesn't exist.
+
+**Example**
+
+```typescript
+// Retrieve a specific vector by key
+const vector = await context.vector.get('product-descriptions', 'chair-001');
+
+if (vector) {
+ console.log(`Found vector: ${vector.id}`);
+ console.log(`Key: ${vector.key}`);
+ console.log(`Metadata:`, vector.metadata);
+} else {
+ console.log('Vector not found');
+}
+```
+
#### delete
`delete(name: string, ...keys: string[]): Promise`
@@ -288,20 +318,20 @@ Returns a Promise that resolves to the number of vectors that were deleted.
**Examples**
```typescript
-// Delete a single vector
-const deletedCount = await context.vector.delete('product-descriptions', 'id1');
+// Delete a single vector by key
+const deletedCount = await context.vector.delete('product-descriptions', 'chair-001');
console.log(`Deleted ${deletedCount} vector(s)`); // Output: Deleted 1 vector(s)
// Delete multiple vectors in bulk (more efficient than individual calls)
-const deletedCount = await context.vector.delete('product-descriptions', 'id1', 'id2', 'id3');
+const deletedCount = await context.vector.delete('product-descriptions', 'chair-001', 'headphones-001', 'desk-002');
console.log(`Deleted ${deletedCount} vector(s)`); // Output: Deleted 3 vector(s)
// Delete with array spread
-const keysToDelete = ['id1', 'id2', 'id3'];
+const keysToDelete = ['chair-001', 'headphones-001', 'desk-002'];
const deletedCount = await context.vector.delete('product-descriptions', ...keysToDelete);
// Handle cases where some vectors might not exist
-const deletedCount = await context.vector.delete('product-descriptions', 'existing-id', 'non-existent-id');
+const deletedCount = await context.vector.delete('product-descriptions', 'existing-key', 'non-existent-key');
console.log(`Deleted ${deletedCount} vector(s)`); // Output: Deleted 1 vector(s)
```
@@ -1451,7 +1481,7 @@ Returns a new `Logger` instance with the additional context.
```typescript
const requestLogger = context.logger.child({ requestId: '123', userId: '456' });
-requestLogger.info('Processing request'); // Includes requestId and userId
+requestLogger.info('Processing request');
```
## Welcome Function
diff --git a/content/SDKs/python/api-reference.mdx b/content/SDKs/python/api-reference.mdx
index a8624310..82b510b1 100644
--- a/content/SDKs/python/api-reference.mdx
+++ b/content/SDKs/python/api-reference.mdx
@@ -493,6 +493,35 @@ except Exception as e:
# Handle the error appropriately
```
+#### get
+
+`async get(name: str, key: str) -> VectorSearchResult | None`
+
+Retrieves a specific vector from the vector storage using its key.
+
+**Parameters**
+
+- `name`: The name of the vector storage
+- `key`: The unique key of the vector to retrieve
+
+**Return Value**
+
+Returns a `VectorSearchResult` object if found, or `None` if the key doesn't exist.
+
+**Example**
+
+```python
+# Retrieve a specific vector by key
+vector = await context.vector.get("product-descriptions", "chair-001")
+
+if vector:
+ print(f"Found vector: {vector.id}")
+ print(f"Key: {vector.key}")
+ print(f"Metadata: {vector.metadata}")
+else:
+ print("Vector not found")
+```
+
#### delete
`async delete(name: str, key: str) -> int`
@@ -596,7 +625,7 @@ user_data = {"name": "John", "age": 30}
await context.objectstore.put("users", "user-123.json", user_data)
# Store binary data
-image_data = bytes([/* image bytes */])
+image_data = b"\x00\x01..." # example bytes
await context.objectstore.put(
"images",
"photo.jpg",
@@ -752,12 +781,13 @@ agent = await context.get_agent({"id": "agent-123"})
# Get an agent by name
agent2 = await context.get_agent({
"name": "data-processing-agent",
- "project_id": "project-456"
+ "projectId": "project-456" # Note: projectId is camelCase
})
# Invoke the agent with error handling
try:
- result = await agent.run({"data": "process this"}, "application/json")
+ # Pass raw payload (content type inferred)
+ result = await agent.run("process this")
# Process the result
print(f"Agent response: {result}")
except Exception as e:
@@ -797,11 +827,11 @@ Returns an `AgentRedirectResponse` object.
```python
# Handoff to another agent
return response.handoff(
- {"name": "data-processing-agent"},
- {"data": "process this"},
- "application/json",
- {"source": "web-agent"}
+ {"name": "data-processing-agent"}, # params
+ "process this", # payload (inferred as text/plain)
+ metadata={"source": "web-agent"} # metadata (keyword arg)
)
+# Note: Python infers content-type from data (string→text/plain, dict→application/json)
```
## Response Types
@@ -991,7 +1021,7 @@ print(f"User ID: {user_id}")
#### json
-`json() -> dict`
+`async json() -> dict`
Gets the payload of the request as a JSON object.
@@ -1008,7 +1038,7 @@ print(f"Request data: {data}")
#### text
-`text() -> str`
+`async text() -> str`
Gets the payload of the request as a string.
@@ -1019,13 +1049,13 @@ Returns the request payload as a string.
**Example**
```python
-text = request.data.text
+text = await request.data.text()
print(f"Request text: {text}")
```
#### binary
-`binary() -> bytes`
+`async binary() -> bytes`
Gets the payload of the request as bytes.
@@ -1036,7 +1066,7 @@ Returns the request payload as bytes.
**Example**
```python
-binary_data = request.binary()
+binary_data = await request.data.binary()
print(f"Binary data size: {len(binary_data)} bytes")
```
@@ -1044,15 +1074,15 @@ print(f"Binary data size: {len(binary_data)} bytes")
The SDK provides specialized methods for various media types:
-- `pdf() -> bytes`
-- `png() -> bytes`
-- `jpeg() -> bytes`
-- `gif() -> bytes`
-- `webp() -> bytes`
-- `mp3() -> bytes`
-- `wav() -> bytes`
-- `ogg() -> bytes`
-- `email() -> Email`
+- `async pdf() -> bytes`
+- `async png() -> bytes`
+- `async jpeg() -> bytes`
+- `async gif() -> bytes`
+- `async webp() -> bytes`
+- `async mp3() -> bytes`
+- `async wav() -> bytes`
+- `async ogg() -> bytes`
+- `async email() -> Email`
Each method returns the request payload as bytes with the appropriate content type validation, except for `email()` which returns an `Email` object.
@@ -1060,17 +1090,17 @@ Each method returns the request payload as bytes with the appropriate content ty
```python
# Get an image from the request
-image = request.png()
+image = await request.data.png()
# Process the image...
# Get audio from the request
-audio = request.mp3()
+audio = await request.data.mp3()
# Process the audio...
```
#### email
-`email() -> Email`
+`async email() -> Email`
Gets the payload of the request as an Email object. This method validates that the content type is `message/rfc822` before parsing.
@@ -1225,97 +1255,98 @@ The Agentuity SDK provides logging functionality through the `context.logger` ob
### Logger Interface
-The `Logger` class defines the following methods:
+The Python SDK provides a standard `logging.Logger` instance through `context.logger`:
```python
-class Logger:
+class Logger(logging.Logger):
"""
Logger for agent execution.
"""
- def debug(self, message: str, *args, **kwargs) -> None:
+ def debug(self, message: str, *args) -> None:
"""Log a debug message."""
pass
- def info(self, message: str, *args, **kwargs) -> None:
+ def info(self, message: str, *args) -> None:
"""Log an informational message."""
pass
- def warn(self, message: str, *args, **kwargs) -> None:
+ def warning(self, message: str, *args) -> None:
"""Log a warning message."""
pass
- def error(self, message: str, *args, **kwargs) -> None:
+ def error(self, message: str, *args) -> None:
"""Log an error message."""
pass
- def child(self, **kwargs) -> 'Logger':
- """Create a child logger with additional context."""
- pass
+ # Note: child() method coming soon for API consistency with JavaScript SDK
```
### Logging Methods
#### debug
-`debug(message: str, *args, **kwargs) -> None`
+`debug(message: str, *args) -> None`
Logs a debug message.
**Parameters**
- `message`: The message to log
-- `args`, `kwargs`: Additional arguments to include in the log
+- `args`: Additional arguments to include in the log
**Example**
```python
-context.logger.debug("Processing request", request_id="123")
+request_id = "123"
+context.logger.debug(f"Processing request request_id={request_id}")
```
#### info
-`info(message: str, *args, **kwargs) -> None`
+`info(message: str, *args) -> None`
Logs an informational message.
**Parameters**
- `message`: The message to log
-- `args`, `kwargs`: Additional arguments to include in the log
+- `args`: Additional arguments to include in the log
**Example**
```python
-context.logger.info("Request processed successfully", request_id="123")
+request_id = "123"
+context.logger.info(f"Request processed successfully request_id={request_id}")
```
-#### warn
+#### warning
-`warn(message: str, *args, **kwargs) -> None`
+`warning(message: str, *args) -> None`
Logs a warning message.
**Parameters**
- `message`: The message to log
-- `args`, `kwargs`: Additional arguments to include in the log
+- `args`: Additional arguments to include in the log
**Example**
```python
-context.logger.warn("Resource not found", resource_id="456")
+resource_id = "456"
+context.logger.warning(f"Resource not found resource_id={resource_id}")
```
#### error
-`error(message: str, *args, **kwargs) -> None`
+`error(message: str, *args) -> None`
Logs an error message.
**Parameters**
- `message`: The message to log
-- `args`, `kwargs`: Additional arguments to include in the log
+- `args`: Additional arguments to include in the log
**Example**
@@ -1324,30 +1355,24 @@ try:
# Some code that might raise an exception
result = process_data()
except Exception as e:
- context.logger.error("Failed to process request", error=str(e))
+ context.logger.error(f"Failed to process request: {str(e)}")
```
### Creating Child Loggers
-#### child
+Child logger functionality is coming soon for API consistency with the JavaScript SDK.
-`child(**kwargs) -> Logger`
-
-Creates a child logger with additional context.
-
-**Parameters**
-
-- `kwargs`: Additional context to include in all logs from the child logger
-
-**Return Value**
-
-Returns a new `Logger` instance with the additional context.
-
-**Example**
+**Current approach (manual context):**
```python
-request_logger = context.logger.child(request_id="123", user_id="456")
-request_logger.info("Processing request") # Includes request_id and user_id
+# Python: Include context in each log message
+request_id = "123"
+user_id = "456"
+endpoint = "/api/users"
+
+context.logger.info(f"Starting request processing request_id={request_id} endpoint={endpoint}")
+context.logger.info(f"User authenticated request_id={request_id} user_id={user_id}")
+context.logger.error(f"Failed to fetch user data request_id={request_id} error={str(error)}")
```
## Telemetry