Skip to content

Commit 2726800

Browse files
update docs and examples
1 parent 721a95d commit 2726800

File tree

12 files changed

+512
-175
lines changed

12 files changed

+512
-175
lines changed

README.md

Lines changed: 202 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# ACI TypeScript SDK
22

3+
[![npm version](https://img.shields.io/npm/v/@aci-sdk/aci.svg)](https://www.npmjs.com/package/@aci-sdk/aci)
4+
35
The official TypeScript SDK for the ACI (Agent-Computer Interface) by Aipolabs. Currently in beta, breaking changes are expected.
46

57
The ACI TypeScript SDK provides convenient access to the ACI REST API from any TypeScript/JavaScript application.
68

9+
## Documentation
10+
The detailed documentation is available [here](https://aci.dev/docs).
11+
712
## Installation
813

914
```bash
@@ -15,48 +20,178 @@ pnpm add @aci-sdk/aci
1520
```
1621

1722
## Usage
23+
ACI platform is built with agent-first principles. Although you can call each of the APIs below any way you prefer in your application, we strongly recommend trying the [Agent-centric features](#agent-centric-features) and taking a look at the [agent examples](https://github.com/aipotheosis-labs/aci-agents/tree/main/examples) to get the most out of the platform and to enable the full potential and vision of future agentic applications.
1824

25+
### Client
1926
```typescript
2027
import { ACI } from '@aci-sdk/aci';
2128

22-
// Initialize the client with configuration
2329
const client = new ACI({
24-
apiKey: process.env.ACI_API_KEY,
25-
// Optional: Configure retry settings
26-
maxRetries: 3,
27-
retryMinWait: 1000,
28-
retryMaxWait: 10000,
29-
retryMultiplier: 2,
30+
// it reads from environment variable by default so you can omit it if you set it in your environment
31+
apiKey: process.env.ACI_API_KEY
3032
});
33+
```
34+
35+
### Apps
36+
#### Types
37+
```typescript
38+
import { AppBasic, AppDetails } from '@aci-sdk/aci';
39+
```
3140

32-
// Search for apps
33-
const apps = await client.apps.search({
41+
#### Methods
42+
```typescript
43+
// search for apps, returns list of basic app data, sorted by relevance to the intent
44+
// all parameters are optional
45+
const apps: AppBasic[] = await client.apps.search({
3446
intent: "I want to search the web",
35-
allowed_apps_only: false,
36-
include_functions: true,
47+
allowed_apps_only: false, // If true, only return apps that are allowed by the agent/accessor, identified by the api key.
48+
include_functions: false, // If true, include functions (name and description) in the search results.
3749
categories: ["search"],
38-
limit: 10
50+
limit: 10,
51+
offset: 0
3952
});
53+
```
4054

41-
// Get app details
42-
const appDetails = await client.apps.get("BRAVE_SEARCH");
55+
```typescript
56+
// get detailed information about an app, including functions supported by the app
57+
const appDetails: AppDetails = await client.apps.get("BRAVE_SEARCH");
58+
```
4359

44-
// Create app configuration
60+
### App Configurations
61+
#### Types
62+
```typescript
63+
import { AppConfiguration } from '@aci-sdk/aci';
64+
import { SecurityScheme } from '@aci-sdk/aci';
65+
```
66+
67+
#### Methods
68+
```typescript
69+
// Create a new app configuration
4570
const configuration = await client.appConfigurations.create(
4671
"GMAIL",
47-
"OAUTH2"
72+
SecurityScheme.OAUTH2
4873
);
74+
```
75+
76+
```typescript
77+
// List app configurations
78+
// All parameters are optional
79+
const configurations: AppConfiguration[] = await client.appConfigurations.list({
80+
app_names: ["GMAIL", "BRAVE_SEARCH"], // Filter by app names
81+
limit: 10, // Maximum number of results
82+
offset: 0 // Pagination offset
83+
});
84+
```
4985

86+
```typescript
87+
// Get app configuration by app name
88+
const configuration: AppConfiguration = await client.appConfigurations.get("GMAIL");
89+
```
90+
91+
```typescript
92+
// Delete an app configuration
93+
await client.appConfigurations.delete("GMAIL");
94+
```
95+
96+
### Linked Accounts
97+
#### Types
98+
```typescript
99+
import { LinkedAccount } from '@aci-sdk/aci';
100+
import { SecurityScheme } from '@aci-sdk/aci';
101+
```
102+
103+
#### Methods
104+
```typescript
50105
// Link an account
106+
// Returns created LinkedAccount for API_KEY and NO_AUTH security schemes
107+
// Returns authorization URL string for OAUTH2 security scheme (you need to finish the flow in browser to create the account)
108+
const result = await client.linkedAccounts.link({
109+
app_name: "BRAVE_SEARCH", // Name of the app to link to
110+
linked_account_owner_id: "user123", // ID to identify the owner of this linked account
111+
security_scheme: SecurityScheme.API_KEY, // Type of authentication
112+
api_key: "your-api-key" // Required for API_KEY security scheme
113+
});
114+
115+
// OAuth2 example (returns auth URL for user to complete OAuth flow in browser)
116+
const oauthUrl = await client.linkedAccounts.link({
117+
app_name: "GMAIL",
118+
linked_account_owner_id: "user123",
119+
security_scheme: SecurityScheme.OAUTH2,
120+
// Optional parameter to redirect to a custom URL after the OAuth2 flow (default to https://platform.aci.dev)
121+
// Note: the url need to be "https"
122+
after_oauth2_link_redirect_url: "https://<your website for your end users>"
123+
});
124+
125+
// No-auth example
51126
const account = await client.linkedAccounts.link({
52-
app_name: "BRAVE_SEARCH",
127+
app_name: "AGENT_SECRETS_MANAGER",
53128
linked_account_owner_id: "user123",
54-
security_scheme: "API_KEY",
55-
api_key: "your-api-key"
129+
security_scheme: SecurityScheme.NO_AUTH
56130
});
131+
```
57132

58-
// Execute a function
59-
const result = await client.functions.execute({
133+
```typescript
134+
// List linked accounts
135+
// All parameters are optional
136+
const accounts: LinkedAccount[] = await client.linkedAccounts.list({
137+
app_name: "BRAVE_SEARCH", // Filter by app name
138+
linked_account_owner_id: "user123" // Filter by owner ID
139+
});
140+
```
141+
142+
```typescript
143+
// Get a specific linked account by ID (note: linked_account_id is different from the linked_account_owner_id)
144+
const account: LinkedAccount = await client.linkedAccounts.get(linked_account_id);
145+
```
146+
147+
```typescript
148+
// Enable a linked account (note: linked_account_id is different from the linked_account_owner_id)
149+
const account: LinkedAccount = await client.linkedAccounts.enable(linked_account_id);
150+
```
151+
152+
```typescript
153+
// Disable a linked account (note: linked_account_id is different from the linked_account_owner_id)
154+
const account: LinkedAccount = await client.linkedAccounts.disable(linked_account_id);
155+
```
156+
157+
```typescript
158+
// Delete a linked account (note: linked_account_id is different from the linked_account_owner_id)
159+
await client.linkedAccounts.delete(linked_account_id);
160+
```
161+
162+
### Functions
163+
#### Types
164+
```typescript
165+
import { FunctionExecutionResult } from '@aci-sdk/aci';
166+
import { FunctionDefinitionFormat } from '@aci-sdk/aci';
167+
```
168+
169+
#### Methods
170+
```typescript
171+
// search for functions, returns list of basic function data, sorted by relevance to the intent
172+
// all parameters are optional
173+
const functions = await client.functions.search({
174+
app_names: ["BRAVE_SEARCH", "TAVILY"],
175+
intent: "I want to search the web",
176+
allowed_apps_only: false, // If true, only returns functions of apps that are allowed by the agent/accessor, identified by the api key.
177+
format: FunctionDefinitionFormat.OPENAI, // The format of the functions, can be OPENAI, ANTHROPIC, BASIC (name and description only)
178+
limit: 10,
179+
offset: 0
180+
});
181+
```
182+
183+
```typescript
184+
// get function definition of a specific function, this is the schema you can feed into LLM
185+
// the actual format is defined by the format parameter: OPENAI, ANTHROPIC, BASIC (name and description only)
186+
const functionDefinition = await client.functions.getDefinition(
187+
"BRAVE_SEARCH__WEB_SEARCH",
188+
FunctionDefinitionFormat.OPENAI
189+
);
190+
```
191+
192+
```typescript
193+
// execute a function with the provided parameters
194+
const result: FunctionExecutionResult = await client.functions.execute({
60195
function_name: "BRAVE_SEARCH__WEB_SEARCH",
61196
function_parameters: { query: { q: "what is the weather in barcelona" } },
62197
linked_account_owner_id: "john_doe"
@@ -69,32 +204,61 @@ if (result.success) {
69204
}
70205
```
71206

72-
## Features
207+
### Agent-centric features
208+
209+
The SDK provides a suite of features and helper functions to make it easier and more seamless to use functions in LLM powered agentic applications.
210+
This is our vision and the recommended way of trying out the SDK.
211+
212+
#### Meta Functions and Unified Function Calling Handler
73213

74-
- Full TypeScript support
75-
- Complete API coverage
76-
- Promise-based async/await interface
77-
- Environment variable support for API key
78-
- Comprehensive type definitions
79-
- Automatic retry mechanism for failed requests
80-
- Resource-based API organization
214+
- A set of meta functions that can be used with LLMs as tools directly. Essentially, they are just the json schema version of some of the backend APIs of ACI.dev. They are provided so that your LLM/Agent can utilize some of the features of ACI.dev directly via function (tool) calling.
81215

82-
## API Reference
216+
- A unified handler for function (tool) calls, which handles both the direct function calls (e.g., BRAVE_SEARCH__WEB_SEARCH) and the meta functions calls (e.g., ACISearchFunctions, ACIExecuteFunction).
83217

84-
The SDK provides the following main features:
218+
```typescript
219+
import { ACI } from '@aci-sdk/aci';
220+
import { FunctionDefinitionFormat } from '@aci-sdk/aci';
221+
222+
const client = new ACI({
223+
apiKey: process.env.ACI_API_KEY
224+
});
85225

86-
- Apps management
87-
- App configurations
88-
- Linked accounts
89-
- Function execution
90-
- Function definitions
226+
// Handle a function call from an LLM
227+
const searchResults = await client.handleFunctionCall({
228+
functionName: 'ACI_SEARCH_FUNCTIONS',
229+
functionArguments: {
230+
intent: "I want to star a GitHub repository",
231+
allowed_apps_only: false,
232+
limit: 10
233+
},
234+
linkedAccountOwnerId: 'user123',
235+
allowedAppsOnly: false,
236+
format: FunctionDefinitionFormat.OPENAI_RESPONSES
237+
});
238+
239+
// The results can be used to execute the found function
240+
if (searchResults.length > 0) {
241+
const executeResult = await client.handleFunctionCall({
242+
functionName: 'ACI_EXECUTE_FUNCTION',
243+
functionArguments: {
244+
function_name: searchResults[0].function.name,
245+
function_arguments: {
246+
// function specific arguments
247+
}
248+
},
249+
linkedAccountOwnerId: 'user123',
250+
allowedAppsOnly: false,
251+
format: FunctionDefinitionFormat.OPENAI_RESPONSES
252+
});
253+
}
254+
```
91255

92-
For detailed API documentation, please refer to the [official ACI documentation](https://docs.aci.dev).
256+
Please see [agent examples](https://github.com/aipotheosis-labs/aci-agents?tab=readme-ov-file#2-agent-with-dynamic-tool-discovery-and-execution) for more advanced and complete examples.
93257

94258
## License
95259

96260
MIT
97261

98262
## Contributing
99263

100-
We wcome contributions! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for details.
264+
We welcome contributions! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for details.

__tests__/meta_functions/aci_execute_function_mock.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ describe('ACI_EXECUTE_FUNCTION Meta Function', () => {
9292
mock.onPost('/functions/calendar_create_event/execute').reply(200, mockResponse);
9393

9494
const linkedAccountOwnerId = 'user-123';
95-
const result = await client.handleFunctionCall(
96-
'ACI_EXECUTE_FUNCTION',
97-
{
95+
const result = await client.handleFunctionCall({
96+
functionName: 'ACI_EXECUTE_FUNCTION',
97+
functionArguments: {
9898
function_name: 'calendar_create_event',
9999
function_arguments: {
100100
title: 'Team Meeting',
@@ -103,7 +103,7 @@ describe('ACI_EXECUTE_FUNCTION Meta Function', () => {
103103
}
104104
},
105105
linkedAccountOwnerId
106-
);
106+
});
107107

108108
expect(mock.history.post.length).toBe(1);
109109
expect(mock.history.post[0].url).toBe('/functions/calendar_create_event/execute');
@@ -123,15 +123,15 @@ describe('ACI_EXECUTE_FUNCTION Meta Function', () => {
123123

124124
const linkedAccountOwnerId = 'user-123';
125125
// Note: function_arguments is not wrapped
126-
const result = await client.handleFunctionCall(
127-
'ACI_EXECUTE_FUNCTION',
128-
{
126+
const result = await client.handleFunctionCall({
127+
functionName: 'ACI_EXECUTE_FUNCTION',
128+
functionArguments: {
129129
function_name: 'calendar_create_event',
130130
title: 'Team Meeting',
131131
start_time: '2023-01-01T10:00:00Z'
132132
},
133133
linkedAccountOwnerId
134-
);
134+
});
135135

136136
expect(mock.history.post.length).toBe(1);
137137
expect(mock.history.post[0].url).toBe('/functions/calendar_create_event/execute');
@@ -154,14 +154,14 @@ describe('ACI_EXECUTE_FUNCTION Meta Function', () => {
154154
mock.onPost('/functions/calendar_create_event/execute').reply(200, errorResponse);
155155

156156
const linkedAccountOwnerId = 'user-123';
157-
const result = await client.handleFunctionCall(
158-
'ACI_EXECUTE_FUNCTION',
159-
{
157+
const result = await client.handleFunctionCall({
158+
functionName: 'ACI_EXECUTE_FUNCTION',
159+
functionArguments: {
160160
function_name: 'calendar_create_event',
161161
function_arguments: { title: 'Meeting' }
162162
},
163163
linkedAccountOwnerId
164-
);
164+
});
165165

166166
expect(mock.history.post.length).toBe(1);
167167
expect(result).toEqual(errorResponse);

__tests__/meta_functions/aci_handle_execution.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ describe('AI Integration Tests', () => {
6262

6363
// Step 2: Handle the ACI search function call
6464
const searchArguments = JSON.parse(searchToolCall.arguments);
65-
const searchResults = await aciClient.handleFunctionCall(
66-
searchToolCall.name,
67-
searchArguments,
68-
'test-user-id', // linkedAccountOwnerId
69-
false, // allowedAppsOnly
70-
FunctionDefinitionFormat.OPENAI_RESPONSES // format
71-
);
65+
const searchResults = await aciClient.handleFunctionCall({
66+
functionName: searchToolCall.name,
67+
functionArguments: searchArguments,
68+
linkedAccountOwnerId: 'test-user-id',
69+
allowedAppsOnly: false,
70+
format: FunctionDefinitionFormat.OPENAI_RESPONSES
71+
});
7272

7373
// Verify we found the GitHub star repository function
7474
expect(Array.isArray(searchResults)).toBe(true);

0 commit comments

Comments
 (0)