Fixie Client Python API Reference

FixieClient

FixieClient is a client to the Fixie system.

Parameters:

Name Type Description Default
api_key Optional[str]

The API key for the Fixie API server. If not provided, the FIXIE_API_KEY environment variable will be used. If that is not set, the authenticated user API key will be used, or a ValueError will be raised if the user is not authenticated.

None
Source code in fixieai/client/client.py
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
class FixieClient:
    """FixieClient is a client to the Fixie system.

    Args:
        api_key: The API key for the Fixie API server. If not provided, the
            FIXIE_API_KEY environment variable will be used. If that is not
            set, the authenticated user API key will be used, or a ValueError
            will be raised if the user is not authenticated.
    """

    def __init__(
        self,
        api_key: Optional[str] = None,
    ):
        self._api_key = api_key or constants.fixie_api_key()
        logging.info(f"Using Fixie API URL: {constants.FIXIE_API_URL}")
        self._request_headers = {"Authorization": f"Bearer {self._api_key}"}
        transport = RequestsHTTPTransport(
            url=constants.FIXIE_GRAPHQL_URL,
            headers=self._request_headers,
        )
        self._gqlclient = Client(transport=transport, fetch_schema_from_transport=False)

    @property
    def gqlclient(self) -> Client:
        """Return the underlying GraphQL client used by this FixieClient."""
        return self._gqlclient

    @property
    def url(self) -> str:
        """Return the URL of the Fixie API server."""
        return constants.FIXIE_API_URL

    def clone(self) -> "FixieClient":
        """Return a new FixieClient instance with the same configuration."""
        return FixieClient(api_key=self._api_key)

    def get_agents(self) -> Dict[str, Dict[str, str]]:
        """Return metadata about all running Fixie Agents. The keys of the returned
        dictionary are the Agent handles, and the values are dictionaries containing
        metadata about each Agent."""

        query = gql(
            """
            query getAgents {
                allAgents {
                    agentId
                    name
                    description
                    moreInfoUrl
                }
            }
        """
        )
        result = self._gqlclient.execute(query)
        assert "allAgents" in result and isinstance(result["allAgents"], list)
        agents = result["allAgents"]
        return {agent["agentId"]: agent for agent in agents}

    def get_agent(self, agent_id: str) -> Agent:
        """Return an existing Agent object."""
        return Agent(self, agent_id)

    def get_agent_page_url(self, agent_id: str) -> str:
        """Return the URL of the Agent page on the Fixie Platform."""
        return f"{constants.FIXIE_AGENT_URL}/{agent_id}"

    def create_agent(
        self,
        handle: str,
        name: str,
        description: str,
        query_url: Optional[str] = None,
        func_url: Optional[str] = None,
        more_info_url: Optional[str] = None,
        published: Optional[bool] = None,
    ) -> Agent:
        """Create a new Agent.

        Args:
            handle: The handle for the new Agent. This must be unique across all
                Agents owned by this user.
            name: The name of the new Agent.
            description: A description of the new Agent.
            query_url: (deprecated) Unused.
            func_url: (deprecated) The URL of the new Agent's func endpoint.
            more_info_url: A URL with more information about the new Agent.
            published: Whether the new Agent should be published.
        """
        agent = Agent(self, f"{self.get_current_username()}/{handle}")
        agent.create_agent(
            name, description, query_url, func_url, more_info_url, published
        )
        return agent

    def get_sessions(self) -> List[str]:
        """Return a list of all session IDs."""

        query = gql(
            """
            query getSessions {
                allSessions {
                    handle
                }
            }
        """
        )
        result = self._gqlclient.execute(query)
        assert "allSessions" in result and isinstance(result["allSessions"], list)
        sessions = result["allSessions"]
        return [session["handle"] for session in sessions]

    def create_session(self, frontend_agent_id: Optional[str] = None) -> Session:
        """Create a new Session."""
        return Session(self, frontend_agent_id=frontend_agent_id)

    def get_session(self, session_id: str) -> Session:
        """Return an existing Session object."""
        return Session(self, session_id)

    def get_current_user(self) -> Dict[str, Any]:
        """Returns the username of the current user."""
        query = gql(
            """
            query getUsername {
                user {
                    username
                    firstName
                    lastName
                    email
                    organization {
                        name
                    }
                    dailyQueryLimit
                    dailyUsedQueries
                    avatar
                }
            }
        """
        )
        result = self._gqlclient.execute(query)
        assert "user" in result and isinstance(result["user"], dict)
        return result["user"]

    def get_current_username(self) -> str:
        """Returns the username of the current user."""
        user = self.get_current_user()
        assert "username" in user and isinstance(user["username"], str)
        return user["username"]

    def refresh_agent(self, agent_handle: str):
        """Indicates that an agent's prompts should be refreshed."""
        username = self.get_current_username()
        requests.post(
            f"{constants.FIXIE_REFRESH_URL}/{username}/{agent_handle}",
            headers=self._request_headers,
        ).raise_for_status()

    def create_agent_revision(
        self,
        handle: str,
        make_current: bool,
        *,
        reindex_corpora: bool = False,
        metadata: Optional[Dict[str, str]] = None,
        external_url: Optional[str] = None,
        python_gzip_tarfile: Optional[BinaryIO] = None,
    ) -> str:
        """Creates a new Agent revision.

        Args:
            handle: The handle of the Agent. Must be owned by the current user.
            make_current: Whether the new revision should be made the current (active) revision.
            reindex_corpora: Whether to reindex all corpora for the new revision.
            metadata: Optional client-provided metadata to associate with the revision.
            external_url: The URL at which the revision is hosted, if hosted externally.
            python_gzip_tarfile: A file-like of a gzip-compressed tarfile containing the files to deploy.

        Exactly one of `external_url` and `python_gzip_tarfile` must be provided.
        """

        mutation = gql(
            """
            mutation CreateAgentRevision(
                $handle: String!,
                $metadata: [RevisionMetadataKeyValuePairInput!]!,
                $makeCurrent: Boolean!,
                $externalDeployment: ExternalDeploymentInput,
                $managedDeployment: ManagedDeploymentInput,
                $reindexCorpora: Boolean!,
            ) {
                createAgentRevision(agentHandle: $handle, makeCurrent: $makeCurrent, revision: { 
                    metadata: $metadata
                    externalDeployment: $externalDeployment
                    managedDeployment: $managedDeployment
                }, reindexCorpora: $reindexCorpora) {
                    revision {
                        id
                    }
                }
            }
            """
        )

        with utils.patched_gql_file_uploader(
            python_gzip_tarfile, "upload.tar.gz", "application/gzip"
        ):
            result = self._gqlclient.execute(
                mutation,
                variable_values={
                    "handle": handle,
                    "metadata": [
                        {"key": key, "value": value} for key, value in metadata.items()
                    ]
                    if metadata
                    else [],
                    "makeCurrent": make_current,
                    "reindexCorpora": reindex_corpora,
                    "externalDeployment": {"url": external_url}
                    if external_url
                    else None,
                    "managedDeployment": {
                        "environment": "PYTHON",
                        "codePackage": python_gzip_tarfile,
                    }
                    if python_gzip_tarfile
                    else None,
                },
                upload_files=True,
            )

        revision_id = result["createAgentRevision"]["revision"]["id"]
        assert isinstance(revision_id, str)
        return revision_id

    def get_current_agent_revision(self, handle: str) -> Optional[str]:
        """Gets the current (active) revision of an agent."""

        query = gql(
            """
            query GetRevisionId($handle: String!) {
                agentByHandle(handle: $handle) {
                    currentRevision {
                        id
                    }
                }
            }
            """
        )

        response = self._gqlclient.execute(
            query,
            variable_values={"handle": handle},
        )

        revision = response["agentByHandle"]["currentRevision"]
        return revision["id"] if revision is not None else None

    def set_current_agent_revision(self, handle: str, revision_id: str):
        """Sets the current (active) revision of an agent."""

        mutation = gql(
            """
            mutation SetCurrentAgentRevision(
                $handle: String!,
                $currentRevisionId: ID!) {
                updateAgent(
                    agentData: {
                        handle: $handle,
                        currentRevisionId: $currentRevisionId
                    }
                ) {
                    agent {
                        agentId
                    }
                }
            }
            """
        )

        _ = self._gqlclient.execute(
            mutation,
            variable_values={"handle": handle, "currentRevisionId": revision_id},
        )

    def delete_agent_revision(self, handle: str, revision_id: str):
        """Deletes an Agent revision."""

        mutation = gql(
            """
            mutation DeleteRevision($handle: String!, $revisionId: ID!) {
                deleteAgentRevision(agentHandle: $handle, revisionId: $revisionId) {
                    agent {
                        agentId
                    }
                }
            }
            """
        )
        _ = self._gqlclient.execute(
            mutation, variable_values={"handle": handle, "revisionId": revision_id}
        )

    def deploy_agent(
        self,
        handle: str,
        gzip_tarfile: BinaryIO,
    ):
        """Deploys an agent implementation.

        Args:
            handle: The handle of the Agent to deploy. Must be owned by the current user.
            gzip_tarfile: A file-like of a gzip-compressed tarfile containing the files to deploy.
        """
        return self.create_agent_revision(
            handle,
            make_current=True,
            python_gzip_tarfile=gzip_tarfile,
        )

gqlclient: Client property

Return the underlying GraphQL client used by this FixieClient.

url: str property

Return the URL of the Fixie API server.

clone()

Return a new FixieClient instance with the same configuration.

Source code in fixieai/client/client.py
90
91
92
def clone(self) -> "FixieClient":
    """Return a new FixieClient instance with the same configuration."""
    return FixieClient(api_key=self._api_key)

create_agent(handle, name, description, query_url=None, func_url=None, more_info_url=None, published=None)

Create a new Agent.

Parameters:

Name Type Description Default
handle str

The handle for the new Agent. This must be unique across all Agents owned by this user.

required
name str

The name of the new Agent.

required
description str

A description of the new Agent.

required
query_url Optional[str]

(deprecated) Unused.

None
func_url Optional[str]

(deprecated) The URL of the new Agent's func endpoint.

None
more_info_url Optional[str]

A URL with more information about the new Agent.

None
published Optional[bool]

Whether the new Agent should be published.

None
Source code in fixieai/client/client.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def create_agent(
    self,
    handle: str,
    name: str,
    description: str,
    query_url: Optional[str] = None,
    func_url: Optional[str] = None,
    more_info_url: Optional[str] = None,
    published: Optional[bool] = None,
) -> Agent:
    """Create a new Agent.

    Args:
        handle: The handle for the new Agent. This must be unique across all
            Agents owned by this user.
        name: The name of the new Agent.
        description: A description of the new Agent.
        query_url: (deprecated) Unused.
        func_url: (deprecated) The URL of the new Agent's func endpoint.
        more_info_url: A URL with more information about the new Agent.
        published: Whether the new Agent should be published.
    """
    agent = Agent(self, f"{self.get_current_username()}/{handle}")
    agent.create_agent(
        name, description, query_url, func_url, more_info_url, published
    )
    return agent

create_agent_revision(handle, make_current, *, reindex_corpora=False, metadata=None, external_url=None, python_gzip_tarfile=None)

Creates a new Agent revision.

Parameters:

Name Type Description Default
handle str

The handle of the Agent. Must be owned by the current user.

required
make_current bool

Whether the new revision should be made the current (active) revision.

required
reindex_corpora bool

Whether to reindex all corpora for the new revision.

False
metadata Optional[Dict[str, str]]

Optional client-provided metadata to associate with the revision.

None
external_url Optional[str]

The URL at which the revision is hosted, if hosted externally.

None
python_gzip_tarfile Optional[BinaryIO]

A file-like of a gzip-compressed tarfile containing the files to deploy.

None

Exactly one of external_url and python_gzip_tarfile must be provided.

Source code in fixieai/client/client.py
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
def create_agent_revision(
    self,
    handle: str,
    make_current: bool,
    *,
    reindex_corpora: bool = False,
    metadata: Optional[Dict[str, str]] = None,
    external_url: Optional[str] = None,
    python_gzip_tarfile: Optional[BinaryIO] = None,
) -> str:
    """Creates a new Agent revision.

    Args:
        handle: The handle of the Agent. Must be owned by the current user.
        make_current: Whether the new revision should be made the current (active) revision.
        reindex_corpora: Whether to reindex all corpora for the new revision.
        metadata: Optional client-provided metadata to associate with the revision.
        external_url: The URL at which the revision is hosted, if hosted externally.
        python_gzip_tarfile: A file-like of a gzip-compressed tarfile containing the files to deploy.

    Exactly one of `external_url` and `python_gzip_tarfile` must be provided.
    """

    mutation = gql(
        """
        mutation CreateAgentRevision(
            $handle: String!,
            $metadata: [RevisionMetadataKeyValuePairInput!]!,
            $makeCurrent: Boolean!,
            $externalDeployment: ExternalDeploymentInput,
            $managedDeployment: ManagedDeploymentInput,
            $reindexCorpora: Boolean!,
        ) {
            createAgentRevision(agentHandle: $handle, makeCurrent: $makeCurrent, revision: { 
                metadata: $metadata
                externalDeployment: $externalDeployment
                managedDeployment: $managedDeployment
            }, reindexCorpora: $reindexCorpora) {
                revision {
                    id
                }
            }
        }
        """
    )

    with utils.patched_gql_file_uploader(
        python_gzip_tarfile, "upload.tar.gz", "application/gzip"
    ):
        result = self._gqlclient.execute(
            mutation,
            variable_values={
                "handle": handle,
                "metadata": [
                    {"key": key, "value": value} for key, value in metadata.items()
                ]
                if metadata
                else [],
                "makeCurrent": make_current,
                "reindexCorpora": reindex_corpora,
                "externalDeployment": {"url": external_url}
                if external_url
                else None,
                "managedDeployment": {
                    "environment": "PYTHON",
                    "codePackage": python_gzip_tarfile,
                }
                if python_gzip_tarfile
                else None,
            },
            upload_files=True,
        )

    revision_id = result["createAgentRevision"]["revision"]["id"]
    assert isinstance(revision_id, str)
    return revision_id

create_session(frontend_agent_id=None)

Create a new Session.

Source code in fixieai/client/client.py
169
170
171
def create_session(self, frontend_agent_id: Optional[str] = None) -> Session:
    """Create a new Session."""
    return Session(self, frontend_agent_id=frontend_agent_id)

delete_agent_revision(handle, revision_id)

Deletes an Agent revision.

Source code in fixieai/client/client.py
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
def delete_agent_revision(self, handle: str, revision_id: str):
    """Deletes an Agent revision."""

    mutation = gql(
        """
        mutation DeleteRevision($handle: String!, $revisionId: ID!) {
            deleteAgentRevision(agentHandle: $handle, revisionId: $revisionId) {
                agent {
                    agentId
                }
            }
        }
        """
    )
    _ = self._gqlclient.execute(
        mutation, variable_values={"handle": handle, "revisionId": revision_id}
    )

deploy_agent(handle, gzip_tarfile)

Deploys an agent implementation.

Parameters:

Name Type Description Default
handle str

The handle of the Agent to deploy. Must be owned by the current user.

required
gzip_tarfile BinaryIO

A file-like of a gzip-compressed tarfile containing the files to deploy.

required
Source code in fixieai/client/client.py
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
def deploy_agent(
    self,
    handle: str,
    gzip_tarfile: BinaryIO,
):
    """Deploys an agent implementation.

    Args:
        handle: The handle of the Agent to deploy. Must be owned by the current user.
        gzip_tarfile: A file-like of a gzip-compressed tarfile containing the files to deploy.
    """
    return self.create_agent_revision(
        handle,
        make_current=True,
        python_gzip_tarfile=gzip_tarfile,
    )

get_agent(agent_id)

Return an existing Agent object.

Source code in fixieai/client/client.py
116
117
118
def get_agent(self, agent_id: str) -> Agent:
    """Return an existing Agent object."""
    return Agent(self, agent_id)

get_agent_page_url(agent_id)

Return the URL of the Agent page on the Fixie Platform.

Source code in fixieai/client/client.py
120
121
122
def get_agent_page_url(self, agent_id: str) -> str:
    """Return the URL of the Agent page on the Fixie Platform."""
    return f"{constants.FIXIE_AGENT_URL}/{agent_id}"

get_agents()

Return metadata about all running Fixie Agents. The keys of the returned dictionary are the Agent handles, and the values are dictionaries containing metadata about each Agent.

Source code in fixieai/client/client.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
def get_agents(self) -> Dict[str, Dict[str, str]]:
    """Return metadata about all running Fixie Agents. The keys of the returned
    dictionary are the Agent handles, and the values are dictionaries containing
    metadata about each Agent."""

    query = gql(
        """
        query getAgents {
            allAgents {
                agentId
                name
                description
                moreInfoUrl
            }
        }
    """
    )
    result = self._gqlclient.execute(query)
    assert "allAgents" in result and isinstance(result["allAgents"], list)
    agents = result["allAgents"]
    return {agent["agentId"]: agent for agent in agents}

get_current_agent_revision(handle)

Gets the current (active) revision of an agent.

Source code in fixieai/client/client.py
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
def get_current_agent_revision(self, handle: str) -> Optional[str]:
    """Gets the current (active) revision of an agent."""

    query = gql(
        """
        query GetRevisionId($handle: String!) {
            agentByHandle(handle: $handle) {
                currentRevision {
                    id
                }
            }
        }
        """
    )

    response = self._gqlclient.execute(
        query,
        variable_values={"handle": handle},
    )

    revision = response["agentByHandle"]["currentRevision"]
    return revision["id"] if revision is not None else None

get_current_user()

Returns the username of the current user.

Source code in fixieai/client/client.py
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
def get_current_user(self) -> Dict[str, Any]:
    """Returns the username of the current user."""
    query = gql(
        """
        query getUsername {
            user {
                username
                firstName
                lastName
                email
                organization {
                    name
                }
                dailyQueryLimit
                dailyUsedQueries
                avatar
            }
        }
    """
    )
    result = self._gqlclient.execute(query)
    assert "user" in result and isinstance(result["user"], dict)
    return result["user"]

get_current_username()

Returns the username of the current user.

Source code in fixieai/client/client.py
201
202
203
204
205
def get_current_username(self) -> str:
    """Returns the username of the current user."""
    user = self.get_current_user()
    assert "username" in user and isinstance(user["username"], str)
    return user["username"]

get_session(session_id)

Return an existing Session object.

Source code in fixieai/client/client.py
173
174
175
def get_session(self, session_id: str) -> Session:
    """Return an existing Session object."""
    return Session(self, session_id)

get_sessions()

Return a list of all session IDs.

Source code in fixieai/client/client.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
def get_sessions(self) -> List[str]:
    """Return a list of all session IDs."""

    query = gql(
        """
        query getSessions {
            allSessions {
                handle
            }
        }
    """
    )
    result = self._gqlclient.execute(query)
    assert "allSessions" in result and isinstance(result["allSessions"], list)
    sessions = result["allSessions"]
    return [session["handle"] for session in sessions]

refresh_agent(agent_handle)

Indicates that an agent's prompts should be refreshed.

Source code in fixieai/client/client.py
207
208
209
210
211
212
213
def refresh_agent(self, agent_handle: str):
    """Indicates that an agent's prompts should be refreshed."""
    username = self.get_current_username()
    requests.post(
        f"{constants.FIXIE_REFRESH_URL}/{username}/{agent_handle}",
        headers=self._request_headers,
    ).raise_for_status()

set_current_agent_revision(handle, revision_id)

Sets the current (active) revision of an agent.

Source code in fixieai/client/client.py
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
def set_current_agent_revision(self, handle: str, revision_id: str):
    """Sets the current (active) revision of an agent."""

    mutation = gql(
        """
        mutation SetCurrentAgentRevision(
            $handle: String!,
            $currentRevisionId: ID!) {
            updateAgent(
                agentData: {
                    handle: $handle,
                    currentRevisionId: $currentRevisionId
                }
            ) {
                agent {
                    agentId
                }
            }
        }
        """
    )

    _ = self._gqlclient.execute(
        mutation,
        variable_values={"handle": handle, "currentRevisionId": revision_id},
    )

get_agents()

Return metadata about all Fixie Agents. The keys of the returned dictionary are Agent IDs, and the values are dictionaries containing metadata about each Agent.

Source code in fixieai/client/client.py
40
41
42
43
44
def get_agents() -> Dict[str, Dict[str, str]]:
    """Return metadata about all Fixie Agents. The keys of the returned
    dictionary are Agent IDs, and the values are dictionaries containing
    metadata about each Agent."""
    return get_client().get_agents()

get_client()

Return the global FixieClient instance.

Source code in fixieai/client/client.py
22
23
24
25
26
27
28
def get_client() -> FixieClient:
    """Return the global FixieClient instance."""
    global _CLIENT
    if not _CLIENT:
        _CLIENT = FixieClient()
    assert _CLIENT is not None
    return _CLIENT

get_embeds()

Return a list of Embeds.

Source code in fixieai/client/client.py
52
53
54
def get_embeds() -> List[Dict[str, Any]]:
    """Return a list of Embeds."""
    return get_session().get_embeds()

get_session()

Return the global Fixie Session instance.

Source code in fixieai/client/client.py
31
32
33
34
35
36
37
def get_session() -> Session:
    """Return the global Fixie Session instance."""
    global _SESSION
    if not _SESSION:
        _SESSION = Session(get_client())
    assert _SESSION is not None
    return _SESSION

query(text)

Run a query.

Source code in fixieai/client/client.py
47
48
49
def query(text: str) -> str:
    """Run a query."""
    return get_session().query(text)

Session

Represents a single session with the Fixie system.

Parameters:

Name Type Description Default
client FixieClient

The FixieClient instance to use.

required
session_id Optional[str]

The ID of the session to use. If not provided, a new session will be created.

None
Source code in fixieai/client/session.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
class Session:
    """Represents a single session with the Fixie system.

    Args:
        client: The FixieClient instance to use.
        session_id: The ID of the session to use. If not provided, a new
            session will be created.
    """

    def __init__(
        self,
        client: FixieClient,
        session_id: Optional[str] = None,
        frontend_agent_id: Optional[str] = None,
    ):
        self._client = client
        self._gqlclient = self._client.gqlclient
        self._session_id = session_id
        if session_id:
            # Test that the session exists.
            _ = self.get_metadata()
            assert (
                frontend_agent_id is None
            ), "Cannot specify frontend_agent_id when using an existing session"
        else:
            self._session_id = self._create_session(frontend_agent_id)
        self._frontend_agent_id: Optional[str] = None
        self._last_message_timestamp: Optional[datetime.datetime] = None

    @property
    def session_id(self) -> Optional[str]:
        """Return the session ID used by this Fixie client."""
        return self._session_id

    @property
    def session_url(self) -> str:
        """Return the URL of the Fixie session."""
        return f"{self._client.url}/sessions/{self.session_id}"

    @property
    def frontend_agent_id(self) -> Optional[str]:
        """Return the frontend agent ID used by this Fixie client."""
        return self._frontend_agent_id

    def clone(self) -> "Session":
        """Return a new Session instance with the same configuration."""
        return Session(self._client.clone(), session_id=self._session_id)

    def _create_session(self, frontend_agent_id: Optional[str] = None) -> str:
        """Create a new session."""
        assert self._session_id is None

        query = gql(
            """
            mutation CreateSession($frontendAgentId: String) {
                createSession(sessionData: {frontendAgentId: $frontendAgentId}) {
                    session {
                        handle
                        frontendAgentId
                    }
                }
            }
            """
        )

        result = self._gqlclient.execute(
            query, variable_values={"frontendAgentId": frontend_agent_id}
        )
        if "createSession" not in result or result["createSession"] is None:
            raise ValueError(f"Failed to create Session")
        assert isinstance(result["createSession"], dict)
        assert isinstance(result["createSession"]["session"], dict)
        self._frontend_agent_id = result["createSession"]["session"]["frontendAgentId"]
        assert isinstance(result["createSession"]["session"]["handle"], str)
        return result["createSession"]["session"]["handle"]

    def get_metadata(self) -> Dict[str, Any]:
        """Return metadata about this session."""

        query = gql(
            """
            query getSession($session_id: String!) {
                sessionByHandle(handle: $session_id) {
                    handle
                    name
                    description
                    frontendAgentId
                }
            }
        """
        )
        result = self._gqlclient.execute(
            query, variable_values={"session_id": self._session_id}
        )
        assert "sessionByHandle" in result and isinstance(
            result["sessionByHandle"], dict
        )
        self._frontend_agent_id = result["sessionByHandle"]["frontendAgentId"]
        return result["sessionByHandle"]

    def delete_session(self) -> None:
        """Delete the current session."""
        query = gql(
            """
            mutation DeleteSession($handle: String!) {
                deleteSession(handle: $handle) {
                    session {
                        handle
                    }
                }
            }
        """
        )
        _ = self._gqlclient.execute(query, variable_values={"handle": self._session_id})

    def get_embeds(self) -> List[Dict[str, Any]]:
        """Return the Embeds attached to this Session."""
        query = gql(
            """
            query getEmbeds($handle: String!) {
                sessionByHandle(handle: $handle) {
                    embeds {
                        key
                        embed {
                            id
                            contentType
                            created
                            contentHash
                            owner {
                                username
                            }
                            url
                        }
                    }
                }
            }
        """
        )
        result = self._gqlclient.execute(
            query, variable_values={"handle": self._session_id}
        )
        assert (
            "sessionByHandle" in result
            and isinstance(result["sessionByHandle"], dict)
            and isinstance(result["sessionByHandle"]["embeds"], list)
        )
        return result["sessionByHandle"]["embeds"]

    def get_messages(self) -> List[Dict[str, Any]]:
        """Return the messages that make up this session."""
        query = gql(
            """
            query getMessages($handle: String!) {
                sessionByHandle(handle: $handle) {
                    messages {
                        id
                        text
                        sentBy {
                            handle
                        }
                        type
                        inReplyTo { id }
                        timestamp
                    }
                }
            }
        """
        )
        result = self._gqlclient.execute(
            query, variable_values={"handle": self._session_id}
        )
        assert (
            "sessionByHandle" in result
            and isinstance(result["sessionByHandle"], dict)
            and isinstance(result["sessionByHandle"]["messages"], list)
        )
        return result["sessionByHandle"]["messages"]

    def add_message(self, text: str) -> str:
        """Add a message to this Session. Returns the added message text."""
        query = gql(
            """
            mutation Post($handle: String!, $text: String!) {
                sendSessionMessage(messageData: {session: $handle, text: $text}) {
                    message {
                        text
                    }
                }
            }
            """
        )
        result = self._gqlclient.execute(
            query, variable_values={"handle": self._session_id, "text": text}
        )
        assert isinstance(result["sendSessionMessage"]["message"]["text"], str)
        return result["sendSessionMessage"]["message"]["text"]

    def query(self, text: str) -> str:
        """Run a single query against the Fixie API and return the response."""
        self.add_message(text)
        # The reply to the query comes in as the most recent 'response' message in the
        # session.
        response = self.get_messages()[-1]
        assert isinstance(response["text"], str)
        return response["text"]

    def run(self, text: str) -> Generator[Dict[str, Any], None, None]:
        """Run a query against the Fixie API, returning a generator that yields
        messages."""

        # Run the query in the background, and continue polling for replies.
        background_client = self.clone()
        threading.Thread(target=background_client.add_message, args=(text,)).start()

        response_received = False
        while not response_received:
            time.sleep(1)
            messages = self.get_messages_since_last_time()
            for message in messages:
                response_received = message["type"] == "response"
                yield message

    def get_messages_since_last_time(self) -> List[Dict[str, Any]]:
        """Return all messages since the given timestamp."""
        timestamp = self._last_message_timestamp
        messages_since_last_time = []
        for message in self.get_messages():
            message_timestamp = datetime.datetime.fromisoformat(message["timestamp"])
            if timestamp is None or message_timestamp > timestamp:
                messages_since_last_time.append(message)
                self._last_message_timestamp = message_timestamp
        return messages_since_last_time

frontend_agent_id: Optional[str] property

Return the frontend agent ID used by this Fixie client.

session_id: Optional[str] property

Return the session ID used by this Fixie client.

session_url: str property

Return the URL of the Fixie session.

add_message(text)

Add a message to this Session. Returns the added message text.

Source code in fixieai/client/session.py
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
def add_message(self, text: str) -> str:
    """Add a message to this Session. Returns the added message text."""
    query = gql(
        """
        mutation Post($handle: String!, $text: String!) {
            sendSessionMessage(messageData: {session: $handle, text: $text}) {
                message {
                    text
                }
            }
        }
        """
    )
    result = self._gqlclient.execute(
        query, variable_values={"handle": self._session_id, "text": text}
    )
    assert isinstance(result["sendSessionMessage"]["message"]["text"], str)
    return result["sendSessionMessage"]["message"]["text"]

clone()

Return a new Session instance with the same configuration.

Source code in fixieai/client/session.py
64
65
66
def clone(self) -> "Session":
    """Return a new Session instance with the same configuration."""
    return Session(self._client.clone(), session_id=self._session_id)

delete_session()

Delete the current session.

Source code in fixieai/client/session.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def delete_session(self) -> None:
    """Delete the current session."""
    query = gql(
        """
        mutation DeleteSession($handle: String!) {
            deleteSession(handle: $handle) {
                session {
                    handle
                }
            }
        }
    """
    )
    _ = self._gqlclient.execute(query, variable_values={"handle": self._session_id})

get_embeds()

Return the Embeds attached to this Session.

Source code in fixieai/client/session.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def get_embeds(self) -> List[Dict[str, Any]]:
    """Return the Embeds attached to this Session."""
    query = gql(
        """
        query getEmbeds($handle: String!) {
            sessionByHandle(handle: $handle) {
                embeds {
                    key
                    embed {
                        id
                        contentType
                        created
                        contentHash
                        owner {
                            username
                        }
                        url
                    }
                }
            }
        }
    """
    )
    result = self._gqlclient.execute(
        query, variable_values={"handle": self._session_id}
    )
    assert (
        "sessionByHandle" in result
        and isinstance(result["sessionByHandle"], dict)
        and isinstance(result["sessionByHandle"]["embeds"], list)
    )
    return result["sessionByHandle"]["embeds"]

get_messages()

Return the messages that make up this session.

Source code in fixieai/client/session.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
def get_messages(self) -> List[Dict[str, Any]]:
    """Return the messages that make up this session."""
    query = gql(
        """
        query getMessages($handle: String!) {
            sessionByHandle(handle: $handle) {
                messages {
                    id
                    text
                    sentBy {
                        handle
                    }
                    type
                    inReplyTo { id }
                    timestamp
                }
            }
        }
    """
    )
    result = self._gqlclient.execute(
        query, variable_values={"handle": self._session_id}
    )
    assert (
        "sessionByHandle" in result
        and isinstance(result["sessionByHandle"], dict)
        and isinstance(result["sessionByHandle"]["messages"], list)
    )
    return result["sessionByHandle"]["messages"]

get_messages_since_last_time()

Return all messages since the given timestamp.

Source code in fixieai/client/session.py
242
243
244
245
246
247
248
249
250
251
def get_messages_since_last_time(self) -> List[Dict[str, Any]]:
    """Return all messages since the given timestamp."""
    timestamp = self._last_message_timestamp
    messages_since_last_time = []
    for message in self.get_messages():
        message_timestamp = datetime.datetime.fromisoformat(message["timestamp"])
        if timestamp is None or message_timestamp > timestamp:
            messages_since_last_time.append(message)
            self._last_message_timestamp = message_timestamp
    return messages_since_last_time

get_metadata()

Return metadata about this session.

Source code in fixieai/client/session.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def get_metadata(self) -> Dict[str, Any]:
    """Return metadata about this session."""

    query = gql(
        """
        query getSession($session_id: String!) {
            sessionByHandle(handle: $session_id) {
                handle
                name
                description
                frontendAgentId
            }
        }
    """
    )
    result = self._gqlclient.execute(
        query, variable_values={"session_id": self._session_id}
    )
    assert "sessionByHandle" in result and isinstance(
        result["sessionByHandle"], dict
    )
    self._frontend_agent_id = result["sessionByHandle"]["frontendAgentId"]
    return result["sessionByHandle"]

query(text)

Run a single query against the Fixie API and return the response.

Source code in fixieai/client/session.py
217
218
219
220
221
222
223
224
def query(self, text: str) -> str:
    """Run a single query against the Fixie API and return the response."""
    self.add_message(text)
    # The reply to the query comes in as the most recent 'response' message in the
    # session.
    response = self.get_messages()[-1]
    assert isinstance(response["text"], str)
    return response["text"]

run(text)

Run a query against the Fixie API, returning a generator that yields messages.

Source code in fixieai/client/session.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
def run(self, text: str) -> Generator[Dict[str, Any], None, None]:
    """Run a query against the Fixie API, returning a generator that yields
    messages."""

    # Run the query in the background, and continue polling for replies.
    background_client = self.clone()
    threading.Thread(target=background_client.add_message, args=(text,)).start()

    response_received = False
    while not response_received:
        time.sleep(1)
        messages = self.get_messages_since_last_time()
        for message in messages:
            response_received = message["type"] == "response"
            yield message

Agent

Provides an interface to the Fixie GraphQL Agent API.

Parameters:

Name Type Description Default
client FixieClient

The FixieClient instance to use.

required
agent_id str

The Agent ID, e.g., "fixie/calc", or handle, e.g., "dice".

required
Source code in fixieai/client/agent.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
class Agent:
    """Provides an interface to the Fixie GraphQL Agent API.

    Args:
        client: The FixieClient instance to use.
        agent_id: The Agent ID, e.g., "fixie/calc", or handle, e.g., "dice".
    """

    def __init__(
        self,
        client: FixieClient,
        agent_id: str,
    ):
        self._client = client
        self._gqlclient = self._client.gqlclient

        self._agent_id = agent_id
        self._owner: Optional[str] = None
        if "/" in agent_id:
            self._owner, self._handle = agent_id.split("/")
        else:
            self._handle = agent_id

        self._metadata: Optional[Dict[str, Any]] = None
        try:
            self._metadata = self.get_metadata()
        except:
            self._metadata = None

    @property
    def agent_id(self) -> str:
        """Return the agentId for this Agent."""
        return self._agent_id

    @property
    def handle(self) -> str:
        """Return the handle for this Agent."""
        return self._handle

    @property
    def valid(self) -> bool:
        """Return whether this Agent is valid."""
        return self._metadata is not None

    @property
    def name(self) -> Optional[str]:
        """Return the name for this Agent."""
        if self._metadata is None:
            return None
        name = self._metadata["name"]
        assert name is None or isinstance(name, str)
        return name

    @property
    def description(self) -> Optional[str]:
        """Return the description for this Agent."""
        if self._metadata is None:
            return None
        description = self._metadata["description"]
        assert description is None or isinstance(description, str)
        return description

    @property
    def queries(self) -> Optional[List[str]]:
        """Return the queries for this Agent."""
        if self._metadata is None:
            return None
        queries = self._metadata["queries"]
        assert queries is None or (
            isinstance(queries, list) and all(isinstance(q, str) for q in queries)
        )
        return queries

    @property
    def more_info_url(self) -> Optional[str]:
        """Return the more info URL for this Agent."""
        if self._metadata is None:
            return None
        more_info_url = self._metadata["moreInfoUrl"]
        assert more_info_url is None or isinstance(more_info_url, str)
        return more_info_url

    @property
    def published(self) -> Optional[bool]:
        """Return the published status for this Agent."""
        if self._metadata is None:
            return None
        published = self._metadata["published"]
        assert published is None or isinstance(published, bool)
        return published

    @property
    def owner(self) -> Optional[str]:
        """Return the owner of this Agent."""
        if self._metadata is None:
            return None
        owner_username = self._metadata["owner"]["username"]
        assert owner_username is None or isinstance(owner_username, str)
        return owner_username

    @property
    def query_url(self) -> Optional[str]:
        """Return the query URL for this Agent."""
        if self._metadata is None:
            return None
        url = self._metadata["queryUrl"]
        assert url is None or isinstance(url, str)
        return url

    @property
    def func_url(self) -> Optional[str]:
        """Return the func URL for this Agent."""
        if self._metadata is None:
            return None
        url = self._metadata["funcUrl"]
        assert url is None or isinstance(url, str)
        return url

    @property
    def created(self) -> Optional[datetime.datetime]:
        """Return the creation timestamp for this Agent."""
        if self._metadata is None:
            return None
        ts = self._metadata["created"]
        if ts is not None:
            return datetime.datetime.fromisoformat(ts)
        else:
            return None

    @property
    def modified(self) -> Optional[datetime.datetime]:
        """Return the modification timestamp for this Agent."""
        if self._metadata is None:
            return None
        ts = self._metadata["modified"]
        if ts is not None:
            return datetime.datetime.fromisoformat(ts)
        else:
            return None

    def get_metadata(self) -> Dict[str, Any]:
        """Return metadata about this Agent."""

        if self._owner is None:
            # Query by handle.
            query = gql(
                """
                query getAgentByHandle($handle: String!) {
                    agentByHandle(handle: $handle) {
                        agentId
                        handle
                        name
                        description
                        queries
                        moreInfoUrl
                        published
                        owner {
                            username
                        }
                        queryUrl
                        funcUrl
                        created
                        modified
                    }
                }
            """
            )
            result = self._gqlclient.execute(
                query, variable_values={"handle": self._handle}
            )
            if "agentByHandle" not in result or result["agentByHandle"] is None:
                raise ValueError(f"Cannot fetch agent metadata for {self._handle}")
            agent_dict = result["agentByHandle"]

        else:
            # Query by agent ID.
            query = gql(
                """
                query getAgentById($agentId: String!) {
                    agentById(agentId: $agentId) {
                        agentId
                        handle
                        name
                        description
                        queries
                        moreInfoUrl
                        published
                        owner {
                            username
                        }
                        queryUrl
                        funcUrl
                        created
                        modified
                    }
                }
            """
            )
            result = self._gqlclient.execute(
                query, variable_values={"agentId": f"{self._owner}/{self._handle}"}
            )
            if "agentById" not in result or result["agentById"] is None:
                raise ValueError(
                    f"Cannot fetch agent metadata for {self._owner}/{self._handle}"
                )
            agent_dict = result["agentById"]

        assert isinstance(agent_dict, dict) and all(
            isinstance(k, str) for k in agent_dict.keys()
        )
        return agent_dict

    def create_agent(
        self,
        name: Optional[str],
        description: str,
        query_url: Optional[str] = None,
        func_url: Optional[str] = None,
        more_info_url: Optional[str] = None,
        published: Optional[bool] = None,
    ) -> str:
        """Create a new Agent with the given parameters."""
        query = gql(
            """
            mutation CreateAgent(
                $handle: String!,
                $name: String,
                $description: String!,
                $queryUrl: String,
                $funcUrl: String,
                $moreInfoUrl: String,
                $published: Boolean) {
                createAgent(
                    agentData: {
                        handle: $handle,
                        name: $name,
                        description: $description,
                        queryUrl: $queryUrl,
                        funcUrl: $funcUrl,
                        moreInfoUrl: $moreInfoUrl,
                        published: $published
                    }
                ) {
                    agent {
                        agentId
                    }
                }
            }
            """
        )

        variable_values: Dict[str, Any] = {"handle": self._handle}
        if name is not None:
            variable_values["name"] = name
        variable_values["description"] = description
        if query_url is not None:
            variable_values["queryUrl"] = query_url
        if func_url is not None:
            warnings.warn(
                "Setting func_url via create_agent is deprecated, use FixieClient.create_agent_revision instead."
            )
            variable_values["funcUrl"] = func_url
        if more_info_url is not None:
            variable_values["moreInfoUrl"] = more_info_url
        if published is not None:
            variable_values["published"] = published

        result = self._gqlclient.execute(query, variable_values=variable_values)
        if "createAgent" not in result or result["createAgent"] is None:
            raise ValueError(f"Failed to create Agent")
        assert isinstance(result["createAgent"], dict)
        assert isinstance(result["createAgent"]["agent"], dict)
        assert isinstance(result["createAgent"]["agent"]["agentId"], str)
        self._metadata = self.get_metadata()
        return result["createAgent"]["agent"]["agentId"]

    def update_agent(
        self,
        new_handle: Optional[str] = None,
        name: Optional[str] = None,
        description: Optional[str] = None,
        query_url: Optional[str] = None,
        func_url: Optional[str] = None,
        more_info_url: Optional[str] = None,
        published: Optional[bool] = None,
    ) -> str:
        """Update the Agent with the given parameters."""
        query = gql(
            """
            mutation UpdateAgent(
                $handle: String!,
                $newHandle: String,
                $name: String,
                $description: String,
                $queryUrl: String,
                $funcUrl: String,
                $moreInfoUrl: String,
                $published: Boolean) {
                updateAgent(
                    agentData: {
                        handle: $handle,
                        newHandle: $newHandle,
                        name: $name,
                        description: $description,
                        queryUrl: $queryUrl,
                        funcUrl: $funcUrl,
                        moreInfoUrl: $moreInfoUrl,
                        published: $published
                    }
                ) {
                    agent {
                        agentId
                    }
                }
            }
            """
        )

        variable_values: Dict[str, Any] = {"handle": self._handle}
        if new_handle is not None:
            variable_values["newHandle"] = new_handle
        if name is not None:
            variable_values["name"] = name
        if description is not None:
            variable_values["description"] = description
        if query_url is not None:
            variable_values["queryUrl"] = query_url
        if func_url is not None:
            warnings.warn(
                "Setting func_url via update_agent is deprecated, use FixieClient.create_agent_revision instead."
            )
            variable_values["funcUrl"] = func_url
        if more_info_url is not None:
            variable_values["moreInfoUrl"] = more_info_url
        if published is not None:
            variable_values["published"] = published

        result = self._gqlclient.execute(query, variable_values=variable_values)
        if "updateAgent" not in result or result["updateAgent"] is None:
            raise ValueError(f"Failed to update Agent")
        assert isinstance(result["updateAgent"], dict)
        assert isinstance(result["updateAgent"]["agent"], dict)
        assert isinstance(result["updateAgent"]["agent"]["agentId"], str)
        self._metadata = self.get_metadata()
        if new_handle:
            self._handle = new_handle
        return result["updateAgent"]["agent"]["agentId"]

    def delete_agent(self) -> None:
        """Delete this Agent."""
        query = gql(
            """
            mutation DeleteAgent($handle: String!) {
                deleteAgent(handle: $handle) {
                    agent {
                        handle
                    }
                }
            }
        """
        )
        _ = self._gqlclient.execute(query, variable_values={"handle": self._handle})

agent_id: str property

Return the agentId for this Agent.

created: Optional[datetime.datetime] property

Return the creation timestamp for this Agent.

description: Optional[str] property

Return the description for this Agent.

func_url: Optional[str] property

Return the func URL for this Agent.

handle: str property

Return the handle for this Agent.

modified: Optional[datetime.datetime] property

Return the modification timestamp for this Agent.

more_info_url: Optional[str] property

Return the more info URL for this Agent.

name: Optional[str] property

Return the name for this Agent.

owner: Optional[str] property

Return the owner of this Agent.

published: Optional[bool] property

Return the published status for this Agent.

queries: Optional[List[str]] property

Return the queries for this Agent.

query_url: Optional[str] property

Return the query URL for this Agent.

valid: bool property

Return whether this Agent is valid.

create_agent(name, description, query_url=None, func_url=None, more_info_url=None, published=None)

Create a new Agent with the given parameters.

Source code in fixieai/client/agent.py
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
def create_agent(
    self,
    name: Optional[str],
    description: str,
    query_url: Optional[str] = None,
    func_url: Optional[str] = None,
    more_info_url: Optional[str] = None,
    published: Optional[bool] = None,
) -> str:
    """Create a new Agent with the given parameters."""
    query = gql(
        """
        mutation CreateAgent(
            $handle: String!,
            $name: String,
            $description: String!,
            $queryUrl: String,
            $funcUrl: String,
            $moreInfoUrl: String,
            $published: Boolean) {
            createAgent(
                agentData: {
                    handle: $handle,
                    name: $name,
                    description: $description,
                    queryUrl: $queryUrl,
                    funcUrl: $funcUrl,
                    moreInfoUrl: $moreInfoUrl,
                    published: $published
                }
            ) {
                agent {
                    agentId
                }
            }
        }
        """
    )

    variable_values: Dict[str, Any] = {"handle": self._handle}
    if name is not None:
        variable_values["name"] = name
    variable_values["description"] = description
    if query_url is not None:
        variable_values["queryUrl"] = query_url
    if func_url is not None:
        warnings.warn(
            "Setting func_url via create_agent is deprecated, use FixieClient.create_agent_revision instead."
        )
        variable_values["funcUrl"] = func_url
    if more_info_url is not None:
        variable_values["moreInfoUrl"] = more_info_url
    if published is not None:
        variable_values["published"] = published

    result = self._gqlclient.execute(query, variable_values=variable_values)
    if "createAgent" not in result or result["createAgent"] is None:
        raise ValueError(f"Failed to create Agent")
    assert isinstance(result["createAgent"], dict)
    assert isinstance(result["createAgent"]["agent"], dict)
    assert isinstance(result["createAgent"]["agent"]["agentId"], str)
    self._metadata = self.get_metadata()
    return result["createAgent"]["agent"]["agentId"]

delete_agent()

Delete this Agent.

Source code in fixieai/client/agent.py
365
366
367
368
369
370
371
372
373
374
375
376
377
378
def delete_agent(self) -> None:
    """Delete this Agent."""
    query = gql(
        """
        mutation DeleteAgent($handle: String!) {
            deleteAgent(handle: $handle) {
                agent {
                    handle
                }
            }
        }
    """
    )
    _ = self._gqlclient.execute(query, variable_values={"handle": self._handle})

get_metadata()

Return metadata about this Agent.

Source code in fixieai/client/agent.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
def get_metadata(self) -> Dict[str, Any]:
    """Return metadata about this Agent."""

    if self._owner is None:
        # Query by handle.
        query = gql(
            """
            query getAgentByHandle($handle: String!) {
                agentByHandle(handle: $handle) {
                    agentId
                    handle
                    name
                    description
                    queries
                    moreInfoUrl
                    published
                    owner {
                        username
                    }
                    queryUrl
                    funcUrl
                    created
                    modified
                }
            }
        """
        )
        result = self._gqlclient.execute(
            query, variable_values={"handle": self._handle}
        )
        if "agentByHandle" not in result or result["agentByHandle"] is None:
            raise ValueError(f"Cannot fetch agent metadata for {self._handle}")
        agent_dict = result["agentByHandle"]

    else:
        # Query by agent ID.
        query = gql(
            """
            query getAgentById($agentId: String!) {
                agentById(agentId: $agentId) {
                    agentId
                    handle
                    name
                    description
                    queries
                    moreInfoUrl
                    published
                    owner {
                        username
                    }
                    queryUrl
                    funcUrl
                    created
                    modified
                }
            }
        """
        )
        result = self._gqlclient.execute(
            query, variable_values={"agentId": f"{self._owner}/{self._handle}"}
        )
        if "agentById" not in result or result["agentById"] is None:
            raise ValueError(
                f"Cannot fetch agent metadata for {self._owner}/{self._handle}"
            )
        agent_dict = result["agentById"]

    assert isinstance(agent_dict, dict) and all(
        isinstance(k, str) for k in agent_dict.keys()
    )
    return agent_dict

update_agent(new_handle=None, name=None, description=None, query_url=None, func_url=None, more_info_url=None, published=None)

Update the Agent with the given parameters.

Source code in fixieai/client/agent.py
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
def update_agent(
    self,
    new_handle: Optional[str] = None,
    name: Optional[str] = None,
    description: Optional[str] = None,
    query_url: Optional[str] = None,
    func_url: Optional[str] = None,
    more_info_url: Optional[str] = None,
    published: Optional[bool] = None,
) -> str:
    """Update the Agent with the given parameters."""
    query = gql(
        """
        mutation UpdateAgent(
            $handle: String!,
            $newHandle: String,
            $name: String,
            $description: String,
            $queryUrl: String,
            $funcUrl: String,
            $moreInfoUrl: String,
            $published: Boolean) {
            updateAgent(
                agentData: {
                    handle: $handle,
                    newHandle: $newHandle,
                    name: $name,
                    description: $description,
                    queryUrl: $queryUrl,
                    funcUrl: $funcUrl,
                    moreInfoUrl: $moreInfoUrl,
                    published: $published
                }
            ) {
                agent {
                    agentId
                }
            }
        }
        """
    )

    variable_values: Dict[str, Any] = {"handle": self._handle}
    if new_handle is not None:
        variable_values["newHandle"] = new_handle
    if name is not None:
        variable_values["name"] = name
    if description is not None:
        variable_values["description"] = description
    if query_url is not None:
        variable_values["queryUrl"] = query_url
    if func_url is not None:
        warnings.warn(
            "Setting func_url via update_agent is deprecated, use FixieClient.create_agent_revision instead."
        )
        variable_values["funcUrl"] = func_url
    if more_info_url is not None:
        variable_values["moreInfoUrl"] = more_info_url
    if published is not None:
        variable_values["published"] = published

    result = self._gqlclient.execute(query, variable_values=variable_values)
    if "updateAgent" not in result or result["updateAgent"] is None:
        raise ValueError(f"Failed to update Agent")
    assert isinstance(result["updateAgent"], dict)
    assert isinstance(result["updateAgent"]["agent"], dict)
    assert isinstance(result["updateAgent"]["agent"]["agentId"], str)
    self._metadata = self.get_metadata()
    if new_handle:
        self._handle = new_handle
    return result["updateAgent"]["agent"]["agentId"]

fixie(ctx)

Command-line interface to the Fixie platform.

Source code in fixieai/cli/cli.py
37
38
39
40
41
@click.group()
@click.pass_context
def fixie(ctx):
    """Command-line interface to the Fixie platform."""
    ctx.ensure_object(CliContext)

Console

A simple console interface for Fixie.

Source code in fixieai/cli/session/console.py
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
class Console:
    """A simple console interface for Fixie."""

    def __init__(
        self,
        client: FixieClient,
        session: Session,
        history_file: str = HISTORY_FILE,
    ):
        self._client = client
        self._session = session
        history_file = os.path.expanduser(history_file)
        os.makedirs(os.path.dirname(history_file), exist_ok=True)
        self._history_file = history_file
        self._response_index = 0

    def run(
        self,
        initial_message: Optional[str] = None,
    ) -> None:
        """Run the console application."""

        textconsole.print("[blue]Welcome to Fixie!")
        textconsole.print(f"Connected to: {self._session.session_url}")

        # Show what's already in the session thus far.
        for message in self._session.get_messages_since_last_time():
            self._show_message(message, show_user_message=True)

        history = prompt_toolkit.history.FileHistory(self._history_file)
        if initial_message:
            prompt_toolkit.print_formatted_text(f"{PROMPT}{initial_message}")
            history.append_string(initial_message)
            self._query(initial_message)

        while True:
            in_text = prompt_toolkit.prompt(
                PROMPT,
                history=history,
                auto_suggest=prompt_toolkit.auto_suggest.AutoSuggestFromHistory(),
            )
            self._query(in_text)

    def _query(self, in_text: str) -> None:
        with textconsole.status("Working...", spinner="bouncingBall"):
            try:
                for message in self._session.run(in_text):
                    self._show_message(message)
            except requests.exceptions.HTTPError as e:
                textconsole.print(f"🚨 {e}")
                return

    def _show_message(self, message: Dict[str, Any], show_user_message: bool = False):
        """Shows a message dict from FixieClient.

        If show_user_message is set, the user messages are also printed with the PROMPT.
        This option is useful for showing previous messages in the chat when connecting
        to a session.
        """
        sender_handle = (
            message["sentBy"]["handle"] if message["sentBy"] else "<unknown>"
        )
        message_text = message["text"]

        if message["type"] == "query" and sender_handle == "user":
            if show_user_message:
                textconsole.print(Markdown(PROMPT + message_text))
        elif message["type"] != "response":
            textconsole.print(
                Markdown(f"   @{sender_handle}: " + message_text, style="dim")
            )
        else:
            self._response_index += 1
            textconsole.print(Markdown(f"{self._response_index}❯ " + message_text))
            self._show_embeds(message["text"])

    def _show_embeds(self, message: str):
        """Shows embeds referenced in `message_text`."""
        # Check embed references in message (denoted by #id).
        embed_ids = _extract_embed_refs(message)
        if not embed_ids:
            return
        # Get a dict of all embed_id -> embeds in the session.
        embeds = {
            embed_dict["key"]: embed_dict["embed"]
            for embed_dict in self._session.get_embeds()
        }
        # Show what we can find.
        for embed_id in embed_ids:
            if embed_id not in embeds:
                textconsole.print(
                    f"   [dim]embed #{embed_id} not found in session[/]", style="red"
                )
                continue
            _show_embed(
                embeds[embed_id]["url"],
                embeds[embed_id]["contentType"],
            )

run(initial_message=None)

Run the console application.

Source code in fixieai/cli/session/console.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
def run(
    self,
    initial_message: Optional[str] = None,
) -> None:
    """Run the console application."""

    textconsole.print("[blue]Welcome to Fixie!")
    textconsole.print(f"Connected to: {self._session.session_url}")

    # Show what's already in the session thus far.
    for message in self._session.get_messages_since_last_time():
        self._show_message(message, show_user_message=True)

    history = prompt_toolkit.history.FileHistory(self._history_file)
    if initial_message:
        prompt_toolkit.print_formatted_text(f"{PROMPT}{initial_message}")
        history.append_string(initial_message)
        self._query(initial_message)

    while True:
        in_text = prompt_toolkit.prompt(
            PROMPT,
            history=history,
            auto_suggest=prompt_toolkit.auto_suggest.AutoSuggestFromHistory(),
        )
        self._query(in_text)