33 |
34 | The OpenAI AI Agent template is a **MINIMAL** template to build an AI Agent that can be hosted on Phala Network's decentralized hosting protocol. Unlike Vercel or other FaaS, it allows you to publish your AI Agent compiled code to IPFS and hosts it on a fully decentralized FaaS cloud with the following benefits:
35 |
36 | - 💨 Ship Fast: Build and ship with familiar toolchain in minutes
37 | - ⛑️ Secure: Execution guarded by rock solid TEE / Intel SGX
38 | - 🔒 Private: Host API keys and user privacy at ease
39 | - 💎 Unstoppable: Powered by IPFS and Phala's 35k+ decentralized TEE workers
40 |
41 | [//]: # ()
42 |
43 | ## Getting Started
44 | ### Prepare
45 | Install dependencies
46 | ```shell
47 | npm install
48 | ```
49 |
50 | ### Testing Locally
51 | Create `.env` file with the default ThirdWeb API key for publishing your Agent Contract to IPFS
52 | ```shell
53 | cp .env.example .env
54 | ```
55 |
56 | Build your Agent
57 | ```shell
58 | npm run build
59 | ```
60 |
61 | Test your Agent locally
62 | ```shell
63 | npm run test
64 | ```
65 |
66 | Expected Test Results
67 | ```shell
68 | INPUT: {"method":"GET","path":"/ipfs/CID","queries":{"chatQuery":["When did humans land on the moon?"],"openAiModel":["gpt-4o"]},"secret":{"openaiApiKey":"YOUR_API_KEY"},"headers":{}}
69 | GET RESULT: {
70 | status: 200,
71 | body: `{"message":"Humans first landed on the moon on July 20, 1969, during NASA's Apollo 11 mission. Astronauts Neil Armstrong and Edwin \\"Buzz\\" Aldrin became the first and second humans to walk on the lunar surface while Michael Collins remained in lunar orbit aboard the Command Module. Neil Armstrong famously declared, \\"That's one small step for man, one giant leap for mankind,\\" as he stepped onto the moon."}`,
72 | headers: {
73 | 'Content-Type': 'application/json',
74 | 'Access-Control-Allow-Origin': '*'
75 | }
76 | }
77 | INPUT: {"method":"POST","path":"/ipfs/CID","queries":{"chatQuery":["When did humans land on the moon?"],"openAiModel":["gpt-4o"]},"secret":{"openaiApiKey":"YOUR_API_KEY"},"headers":{},"body":"{}"}
78 | POST RESULT: {
79 | status: 200,
80 | body: '{"message":"Not Implemented"}',
81 | headers: {
82 | 'Content-Type': 'application/json',
83 | 'Access-Control-Allow-Origin': '*'
84 | }
85 | }
86 | Now you are ready to publish your agent, add secrets, and interact with your agent in the following steps:
87 | - Execute: 'npm run publish-agent'
88 | - Set secrets: 'npm run set-secrets'
89 | - Go to the url produced by setting the secrets (e.g. https://wapo-testnet.phala.network/ipfs/QmPQJD5zv3cYDRM25uGAVjLvXGNyQf9Vonz7rqkQB52Jae?key=b092532592cbd0cf)
90 | ```
91 |
92 | ### Publish Your AI Agent
93 | Upload your compiled AI Agent code to IPFS.
94 | ```shell
95 | npm run publish-agent
96 | ```
97 |
98 | Upon a successful upload, the command should show the URL to access your AI Agent.
99 | ```shell
100 | ✓ Compiled successfully.
101 | 76.86 KB dist/index.js
102 | Running command: npx thirdweb upload dist/index.js
103 | This may require you to log into thirdweb and will take some time to publish to IPFS...
104 |
105 | $$\ $$\ $$\ $$\ $$\
106 | $$ | $$ | \__| $$ | $$ |
107 | $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$$$$$$ |$$\ $$\ $$\ $$$$$$\ $$$$$$$\
108 | \_$$ _| $$ __$$\ $$ |$$ __$$\ $$ __$$ |$$ | $$ | $$ |$$ __$$\ $$ __$$\
109 | $$ | $$ | $$ |$$ |$$ | \__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ |
110 | $$ |$$\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ |
111 | \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
112 | \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/
113 |
114 | 💎 thirdweb v0.14.12 💎
115 |
116 | - Uploading file to IPFS. This may take a while depending on file sizes.
117 |
118 | ✔ Successfully uploaded file to IPFS.
119 | ✔ Files stored at the following IPFS URI: ipfs://QmdBwRk3YG78thoe9phf43CLAzShYUEiPHnWBu6bkqsJVY
120 | ✔ Open this link to view your upload: https://b805a9b72767504353244e0422c2b5f9.ipfscdn.io/ipfs/bafybeig4up5mjx6kvkm5dizsv2njpkzk7pileis3kfheyd5wff2m3wbtrm/
121 |
122 | Agent Contract deployed at: https://wapo-testnet.phala.network/ipfs/QmdBwRk3YG78thoe9phf43CLAzShYUEiPHnWBu6bkqsJVY
123 |
124 | If your agent requires secrets, ensure to do the following:
125 | 1) Edit the ./secrets/default.json file or create a new JSON file in the ./secrets folder and add your secrets to it.
126 | 2) Run command: 'npm run set-secrets' or 'npm run set-secrets [path-to-json-file]'
127 | Logs folder created.
128 | Deployment information updated in ./logs/latestDeployment.json
129 | ```
130 |
131 | > :information_source: Note that your latest deployment information will be logged to in file [`./logs/latestDeployment.json`](./logs/latestDeployment.json). This file is updated every time you publish a new Agent Contract to IPFS. This file is also used to get the IPFS CID of your Agent Contract when setting secrets for your Agent Contract.
132 | >
133 | > Here is an example:
134 | > ```json
135 | > {
136 | > "date": "2024-08-29T20:28:20.081Z",
137 | > "cid": "QmYzBTdQNPewdhD9GdBJ9TdV7LVhrh9YVRiV8aBup7qZGu",
138 | > "url": "https://wapo-testnet.phala.network/ipfs/QmYzBTdQNPewdhD9GdBJ9TdV7LVhrh9YVRiV8aBup7qZGu"
139 | > }
140 | > ```
141 |
142 |
143 | New to Thirdweb?
144 | We use thirdweb Storage to host IPFS contents. If you are new to thirdweb, the command will guide you to create your account or login to your existing account from the browser.
145 |
146 |
147 | > **Did Thirdweb fail to publish?**
148 | >
149 | > If ThirdWeb fails to publish, please signup for your own ThirdWeb account to publish your Agent Contract to IPFS. Signup or login at https://thirdweb.com/dashboard/
150 | >
151 | > Whenever you log into ThirdWeb, create a new API key and replace the default API Key with yours in the [.env](./.env) file.
152 | >
153 | > ```
154 | > THIRDWEB_API_KEY="YOUR_THIRDWEB_API_KEY"
155 | > ```
156 |
157 | ### Access the Published AI Agent
158 |
159 | Once published, your AI Agent is available at the URL: `https://wapo-testnet.phala.network/ipfs/`. You can get it from the "Publish to IPFS" step.
160 |
161 | You can test it with `curl`.
162 |
163 | ```bash
164 | curl https://wapo-testnet.phala.network/ipfs/
165 | ```
166 |
167 | ### Add Secrets
168 |
169 | By default, all the compiled JS code is visible for anyone to view if they look at IPFS CID. This makes private info like API keys, signer keys, etc. vulnerable to be stolen. To protect devs from leaking keys, we have added a field called `secret` in the `Request` object. It allows you to store secrets in a vault for your AI Agent to access.
170 |
171 | To add your secrets,
172 | 1) Edit the [default.json](./secrets/default.json) file or create a new JSON file in the `./secrets` folder and add your secrets to it.
173 | ```json
174 | {
175 | "openaiApiKey": "YOUR_OPENAI_API_KEY"
176 | }
177 | ```
178 | 2) Run command to set the secrets
179 | ```shell
180 | npm run set-secrets
181 | # or if you have a custom JSON file
182 | npm run set-secrets
183 | ```
184 | Expected output:
185 | ```shell
186 | Use default secrets...
187 | Storing secrets...
188 | % Total % Received % Xferd Average Speed Time Time Time Current
189 | Dload Upload Total Spent Left Speed
190 | 100 205 0 68 100 137 105 213 --:--:-- --:--:-- --:--:-- 319
191 | {"token":"37a0f3f344a3bbf7","key":"343e2a7dc130fedf","succeed":true}
192 |
193 | Secrets set successfully. Go to the URL below to interact with your agent:
194 | https://wapo-testnet.phala.network/ipfs/QmYzBTdQNPewdhD9GdBJ9TdV7LVhrh9YVRiV8aBup7qZGu?key=343e2a7dc130fedf
195 | Log entry added to secrets.log
196 | ```
197 |
198 | > :information_source: Note that all your secrets will be logged in file [`./logs/secrets.log`](./logs/secrets.log). This file is updated every time you add new secrets to your Agent Contract. If you have not published an Agent Contract, yet, this command will fail since there is not a CID to map the secrets to.
199 | >
200 | > Here is an example:
201 | > ```text
202 | > 2024-08-29T20:30:35.480Z, CID: [QmYzBTdQNPewdhD9GdBJ9TdV7LVhrh9YVRiV8aBup7qZGu], Token: [37a0f3f344a3bbf7], Key: [343e2a7dc130fedf], URL: [https://wapo-testnet.phala.network/ipfs/QmYzBTdQNPewdhD9GdBJ9TdV7LVhrh9YVRiV8aBup7qZGu?key=343e2a7dc130fedf]
203 | > ```
204 |
205 | The API returns a `token` and a `key`. The `key` is the id of your secret. It can be used to specify which secret you are going to pass to your frame. The `token` can be used by the developer to access the raw secret. You should never leak the `token`.
206 |
207 | To verify the secret, run the following command where `key` and `token` are replaced with the values from adding your `secret` to the vault.
208 | ```shell
209 | curl https://wapo-testnet.phala.network/vaults//
210 | ```
211 |
212 | Expected output:
213 | ```shell
214 | {"data":{"openaiApiKey":""},"succeed":true}
215 | ```
216 |
217 | ### Access Queries
218 | To help create custom logic, we have an array variable named `queries` that can be accessed in the `Request` class. To access the `queries` array variable `chatQuery` value at index `0`, the syntax will look as follows:
219 | ```typescript
220 | const query = req.queries.chatQuery[0] as string;
221 | ```
222 | The example at https://wapo-testnet.phala.network/ipfs/QmcQbQzJop8m9uqGJTRmxVCEPoWtzx6NkNJRA12CZ6vFyT?key=b7fd2b6c4bf008cc&chatQuery=When%20did%20humans%20land%20on%20the%20moon will have a value of `When did humans land on the moon`. `queries` can have any field name, so `chatQuery` is just an example of a field name and not a mandatory name, but remember to update your `index.ts` file logic to use your expected field name.
223 |
224 | ### Debugging
225 |
226 | To debug your agent, you can use the following command:
227 | ```shell
228 | curl https://wapo-testnet.phala.network/logs/all/ipfs/
229 | ```
230 |
231 | After executing this command then you should see some output in the terminal to show the logs of requests to your agent.
232 | ```shell
233 | 2024-09-04T03:18:34.758Z [95f5ec53-3d71-4bb5-bbb6-66065211102c] [REPORT] END Request: Duration: 166ms
234 | 2024-09-04T03:18:34.758Z [95f5ec53-3d71-4bb5-bbb6-66065211102c] [INFO] 'Is signature valid? ' true
235 | 2024-09-04T03:18:34.758Z [95f5ec53-3d71-4bb5-bbb6-66065211102c] [INFO] 'Verifying Signature with PublicKey ' '0xC1BF8dB4D06416c43Aca3deB289CF7CC0aAFF540'
236 | 2024-09-04T03:18:34.758Z [95f5ec53-3d71-4bb5-bbb6-66065211102c] [REPORT] START Request: GET /ipfs/QmfLpQjxAMsppUX9og7xpmfSKZAZ8zuWJV5g42DmpASSWz?key=0e26a64a1e805bfd&type=verify&data=tintinland%20message%20to%20sign&signature=0x34c4d8c83406e7a292ecc940d60b34c9b11024db10a8872c753b9711cd6dbc8f746da8be9bc2ae0898ebf8f49f48c2ff4ba2a851143c3e4b371647eed32f707b1b
237 | 2024-09-04T03:17:15.238Z [768b6fda-f9f1-463f-86bd-a948e002bf80] [REPORT] END Request: Duration: 183ms
238 | 2024-09-04T03:17:15.238Z [768b6fda-f9f1-463f-86bd-a948e002bf80] [INFO] 'Signature: 0x34c4d8c83406e7a292ecc940d60b34c9b11024db10a8872c753b9711cd6dbc8f746da8be9bc2ae0898ebf8f49f48c2ff4ba2a851143c3e4b371647eed32f707b1b'
239 | 2024-09-04T03:17:15.238Z [768b6fda-f9f1-463f-86bd-a948e002bf80] [INFO] 'Signing data [tintinland message to sign] with Account [0xC1BF8dB4D06416c43Aca3deB289CF7CC0aAFF540]'
240 | 2024-09-04T03:17:15.238Z [768b6fda-f9f1-463f-86bd-a948e002bf80] [REPORT] START Request: GET /ipfs/QmfLpQjxAMsppUX9og7xpmfSKZAZ8zuWJV5g42DmpASSWz?key=0e26a64a1e805bfd&type=sign&data=tintinland%20message%20to%20sign
241 | 2024-09-04T03:16:38.507Z [3717d307-bff0-4fc0-bc98-8f66c33dd46f] [REPORT] END Request: Duration: 169ms
242 | 2024-09-04T03:16:38.507Z [3717d307-bff0-4fc0-bc98-8f66c33dd46f] [REPORT] START Request: GET /ipfs/QmfLpQjxAMsppUX9og7xpmfSKZAZ8zuWJV5g42DmpASSWz?key=0e26a64a1e805bfd
243 | 2024-09-04T03:15:00.375Z [793f58f9-f24f-4580-8ebc-04debb7d727f] [REPORT] END Request: Duration: 158ms
244 | 2024-09-04T03:15:00.375Z [793f58f9-f24f-4580-8ebc-04debb7d727f] [REPORT] START Request: GET /ipfs/QmfLpQjxAMsppUX9og7xpmfSKZAZ8zuWJV5g42DmpASSWz?key=0e26a64
245 | a1e805bfd
246 | ```
247 | To create logs in your Agent Contract, you can use the following syntax in your `index.ts` file.
248 | ```typescript
249 | // info logs
250 | console.log('info log message!')
251 | // error logs
252 | console.error('error log message!')
253 | ```
254 | For more information check the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/console) on `console` object.
255 |
256 | ## FAQ
257 |
258 |
259 | What packages can I use in the AI Agent server?
260 |
261 |
Most of the npm packages are supported: viem, onchainkit, ….
262 |
Some packages with some advanced features are not supported:
263 |
264 |
Memory usage over 100MB
265 |
Web Assembly
266 |
Browser only features: local storage, service workers, etc
267 |
268 |
269 |
270 |
271 |
272 | What’s the spec of the Javascript runtime?
273 |
278 |
279 |
280 |
281 | Why is the serverless platform secure?
282 |
283 |
Your AI Agent code on is fully secure, private, and permissionless. Nobody can manipulate your program, steal any data from it, or censor it.
284 |
Security: The code is executed in the decentralized TEE network running on Phala Network. It runs code inside a secure blackbox (called enclave) created by the CPU. It generates cryptographic proofs verifiable on Phala blockchain. It proves that the hosted code is exactly the one you deployed.
285 |
Privacy: You can safely put secrets like API keys or user privacy on Phala Network. The code runs inside TEE hardware blackboxs. The memory of the program is fully encrypted by the TEE. It blocks any unauthorized access to your data.