about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-11-16 18:26:22 -0800
committerGitHub <noreply@github.com>2023-11-16 18:26:22 -0800
commit357c752a213dbcf77e5333fa180cfef20a33842d (patch)
treee955e57cc1252b5fe759cde29185d62bb71bc339 /src
parent3043b324681f1702ca53831701fb5cecd14c0efb (diff)
downloadvoidsky-357c752a213dbcf77e5333fa180cfef20a33842d.tar.zst
Move the current agent to a global and reset RQ queries on agent change (#1946)
Diffstat (limited to 'src')
-rw-r--r--src/state/queries/actor-autocomplete.ts10
-rw-r--r--src/state/queries/app-passwords.ts11
-rw-r--r--src/state/queries/feed.ts21
-rw-r--r--src/state/queries/handle.ts15
-rw-r--r--src/state/queries/invites.ts6
-rw-r--r--src/state/queries/like.ts10
-rw-r--r--src/state/queries/list-members.ts5
-rw-r--r--src/state/queries/list-memberships.ts14
-rw-r--r--src/state/queries/list.ts49
-rw-r--r--src/state/queries/my-blocked-accounts.ts5
-rw-r--r--src/state/queries/my-follows.ts6
-rw-r--r--src/state/queries/my-lists.ts16
-rw-r--r--src/state/queries/my-muted-accounts.ts5
-rw-r--r--src/state/queries/notifications/feed.ts7
-rw-r--r--src/state/queries/notifications/unread.tsx12
-rw-r--r--src/state/queries/post-feed.ts4
-rw-r--r--src/state/queries/post-liked-by.ts5
-rw-r--r--src/state/queries/post-reposted-by.ts5
-rw-r--r--src/state/queries/post-thread.ts5
-rw-r--r--src/state/queries/post.ts27
-rw-r--r--src/state/queries/preferences/index.ts39
-rw-r--r--src/state/queries/profile-extra-info.ts7
-rw-r--r--src/state/queries/profile-feedgens.ts5
-rw-r--r--src/state/queries/profile-followers.ts5
-rw-r--r--src/state/queries/profile-follows.ts5
-rw-r--r--src/state/queries/profile-lists.ts5
-rw-r--r--src/state/queries/profile.ts34
-rw-r--r--src/state/queries/resolve-uri.ts5
-rw-r--r--src/state/queries/search-posts.ts6
-rw-r--r--src/state/queries/suggested-feeds.ts6
-rw-r--r--src/state/queries/suggested-follows.ts20
-rw-r--r--src/state/session/index.tsx31
-rw-r--r--src/view/com/composer/Composer.tsx6
-rw-r--r--src/view/com/composer/useExternalLinkFetch.ts11
-rw-r--r--src/view/com/modals/ChangeEmail.tsx10
-rw-r--r--src/view/com/modals/ChangeHandle.tsx11
-rw-r--r--src/view/com/modals/DeleteAccount.tsx8
-rw-r--r--src/view/com/modals/VerifyEmail.tsx8
-rw-r--r--src/view/com/modals/report/Modal.tsx5
-rw-r--r--src/view/screens/Settings.tsx13
40 files changed, 218 insertions, 260 deletions
diff --git a/src/state/queries/actor-autocomplete.ts b/src/state/queries/actor-autocomplete.ts
index e7a8eb30d..fbd1b38f9 100644
--- a/src/state/queries/actor-autocomplete.ts
+++ b/src/state/queries/actor-autocomplete.ts
@@ -3,14 +3,13 @@ import {AppBskyActorDefs} from '@atproto/api'
 import {useQuery, useQueryClient} from '@tanstack/react-query'
 
 import {logger} from '#/logger'
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {useMyFollowsQuery} from '#/state/queries/my-follows'
 import {STALE} from '#/state/queries'
 
 export const RQKEY = (prefix: string) => ['actor-autocomplete', prefix]
 
 export function useActorAutocompleteQuery(prefix: string) {
-  const {agent} = useSession()
   const {data: follows, isFetching} = useMyFollowsQuery()
 
   return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
@@ -18,7 +17,7 @@ export function useActorAutocompleteQuery(prefix: string) {
     queryKey: RQKEY(prefix || ''),
     async queryFn() {
       const res = prefix
-        ? await agent.searchActorsTypeahead({
+        ? await getAgent().searchActorsTypeahead({
             term: prefix,
             limit: 8,
           })
@@ -32,7 +31,6 @@ export function useActorAutocompleteQuery(prefix: string) {
 export type ActorAutocompleteFn = ReturnType<typeof useActorAutocompleteFn>
 export function useActorAutocompleteFn() {
   const queryClient = useQueryClient()
-  const {agent} = useSession()
   const {data: follows} = useMyFollowsQuery()
 
   return React.useCallback(
@@ -44,7 +42,7 @@ export function useActorAutocompleteFn() {
             staleTime: STALE.MINUTES.ONE,
             queryKey: RQKEY(query || ''),
             queryFn: () =>
-              agent.searchActorsTypeahead({
+              getAgent().searchActorsTypeahead({
                 term: query,
                 limit,
               }),
@@ -58,7 +56,7 @@ export function useActorAutocompleteFn() {
 
       return computeSuggestions(query, follows, res?.data.actors)
     },
-    [agent, follows, queryClient],
+    [follows, queryClient],
   )
 }
 
diff --git a/src/state/queries/app-passwords.ts b/src/state/queries/app-passwords.ts
index 9aadfe2e4..6a7e43610 100644
--- a/src/state/queries/app-passwords.ts
+++ b/src/state/queries/app-passwords.ts
@@ -1,25 +1,23 @@
 import {ComAtprotoServerCreateAppPassword} from '@atproto/api'
 import {useQuery, useQueryClient, useMutation} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '../session'
 
 export const RQKEY = () => ['app-passwords']
 
 export function useAppPasswordsQuery() {
-  const {agent} = useSession()
   return useQuery({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(),
     queryFn: async () => {
-      const res = await agent.com.atproto.server.listAppPasswords({})
+      const res = await getAgent().com.atproto.server.listAppPasswords({})
       return res.data.passwords
     },
   })
 }
 
 export function useAppPasswordCreateMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<
     ComAtprotoServerCreateAppPassword.OutputSchema,
@@ -28,7 +26,7 @@ export function useAppPasswordCreateMutation() {
   >({
     mutationFn: async ({name}) => {
       return (
-        await agent.com.atproto.server.createAppPassword({
+        await getAgent().com.atproto.server.createAppPassword({
           name,
         })
       ).data
@@ -42,11 +40,10 @@ export function useAppPasswordCreateMutation() {
 }
 
 export function useAppPasswordDeleteMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, {name: string}>({
     mutationFn: async ({name}) => {
-      await agent.com.atproto.server.revokeAppPassword({
+      await getAgent().com.atproto.server.revokeAppPassword({
         name,
       })
     },
diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts
index f7692aff3..e3bcbc83e 100644
--- a/src/state/queries/feed.ts
+++ b/src/state/queries/feed.ts
@@ -18,7 +18,7 @@ import {
 import {router} from '#/routes'
 import {sanitizeDisplayName} from '#/lib/strings/display-names'
 import {sanitizeHandle} from '#/lib/strings/handles'
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {usePreferencesQuery} from '#/state/queries/preferences'
 import {STALE} from '#/state/queries'
 
@@ -136,7 +136,6 @@ export function getFeedTypeFromUri(uri: string) {
 }
 
 export function useFeedSourceInfoQuery({uri}: {uri: string}) {
-  const {agent} = useSession()
   const type = getFeedTypeFromUri(uri)
 
   return useQuery({
@@ -146,10 +145,10 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
       let view: FeedSourceInfo
 
       if (type === 'feed') {
-        const res = await agent.app.bsky.feed.getFeedGenerator({feed: uri})
+        const res = await getAgent().app.bsky.feed.getFeedGenerator({feed: uri})
         view = hydrateFeedGenerator(res.data.view)
       } else {
-        const res = await agent.app.bsky.graph.getList({
+        const res = await getAgent().app.bsky.graph.getList({
           list: uri,
           limit: 1,
         })
@@ -164,8 +163,6 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
 export const useGetPopularFeedsQueryKey = ['getPopularFeeds']
 
 export function useGetPopularFeedsQuery() {
-  const {agent} = useSession()
-
   return useInfiniteQuery<
     AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema,
     Error,
@@ -175,7 +172,7 @@ export function useGetPopularFeedsQuery() {
   >({
     queryKey: useGetPopularFeedsQueryKey,
     queryFn: async ({pageParam}) => {
-      const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
+      const res = await getAgent().app.bsky.unspecced.getPopularFeedGenerators({
         limit: 10,
         cursor: pageParam,
       })
@@ -187,11 +184,9 @@ export function useGetPopularFeedsQuery() {
 }
 
 export function useSearchPopularFeedsMutation() {
-  const {agent} = useSession()
-
   return useMutation({
     mutationFn: async (query: string) => {
-      const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
+      const res = await getAgent().app.bsky.unspecced.getPopularFeedGenerators({
         limit: 10,
         query: query,
       })
@@ -220,7 +215,6 @@ const FOLLOWING_FEED_STUB: FeedSourceInfo = {
 }
 
 export function usePinnedFeedsInfos(): FeedSourceInfo[] {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   const [tabs, setTabs] = React.useState<FeedSourceInfo[]>([
     FOLLOWING_FEED_STUB,
@@ -250,12 +244,12 @@ export function usePinnedFeedsInfos(): FeedSourceInfo[] {
                 const type = getFeedTypeFromUri(uri)
 
                 if (type === 'feed') {
-                  const res = await agent.app.bsky.feed.getFeedGenerator({
+                  const res = await getAgent().app.bsky.feed.getFeedGenerator({
                     feed: uri,
                   })
                   return hydrateFeedGenerator(res.data.view)
                 } else {
-                  const res = await agent.app.bsky.graph.getList({
+                  const res = await getAgent().app.bsky.graph.getList({
                     list: uri,
                     limit: 1,
                   })
@@ -274,7 +268,6 @@ export function usePinnedFeedsInfos(): FeedSourceInfo[] {
 
     fetchFeedInfo()
   }, [
-    agent,
     queryClient,
     setTabs,
     preferences?.feeds?.pinned,
diff --git a/src/state/queries/handle.ts b/src/state/queries/handle.ts
index d73e068ec..d7c411699 100644
--- a/src/state/queries/handle.ts
+++ b/src/state/queries/handle.ts
@@ -1,14 +1,13 @@
 import React from 'react'
 import {useQueryClient, useMutation} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const fetchHandleQueryKey = (handleOrDid: string) => ['handle', handleOrDid]
 const fetchDidQueryKey = (handleOrDid: string) => ['did', handleOrDid]
 
 export function useFetchHandle() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return React.useCallback(
@@ -17,23 +16,22 @@ export function useFetchHandle() {
         const res = await queryClient.fetchQuery({
           staleTime: STALE.MINUTES.FIVE,
           queryKey: fetchHandleQueryKey(handleOrDid),
-          queryFn: () => agent.getProfile({actor: handleOrDid}),
+          queryFn: () => getAgent().getProfile({actor: handleOrDid}),
         })
         return res.data.handle
       }
       return handleOrDid
     },
-    [agent, queryClient],
+    [queryClient],
   )
 }
 
 export function useUpdateHandleMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation({
     mutationFn: async ({handle}: {handle: string}) => {
-      await agent.updateHandle({handle})
+      await getAgent().updateHandle({handle})
     },
     onSuccess(_data, variables) {
       queryClient.invalidateQueries({
@@ -44,7 +42,6 @@ export function useUpdateHandleMutation() {
 }
 
 export function useFetchDid() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return React.useCallback(
@@ -55,13 +52,13 @@ export function useFetchDid() {
         queryFn: async () => {
           let identifier = handleOrDid
           if (!identifier.startsWith('did:')) {
-            const res = await agent.resolveHandle({handle: identifier})
+            const res = await getAgent().resolveHandle({handle: identifier})
             identifier = res.data.did
           }
           return identifier
         },
       })
     },
-    [agent, queryClient],
+    [queryClient],
   )
 }
diff --git a/src/state/queries/invites.ts b/src/state/queries/invites.ts
index ca850d1b6..c42ba29d5 100644
--- a/src/state/queries/invites.ts
+++ b/src/state/queries/invites.ts
@@ -1,7 +1,7 @@
 import {ComAtprotoServerDefs} from '@atproto/api'
 import {useQuery} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean {
@@ -13,13 +13,11 @@ export type InviteCodesQueryResponse = Exclude<
   undefined
 >
 export function useInviteCodesQuery() {
-  const {agent} = useSession()
-
   return useQuery({
     staleTime: STALE.HOURS.ONE,
     queryKey: ['inviteCodes'],
     queryFn: async () => {
-      const res = await agent.com.atproto.server.getAccountInviteCodes({})
+      const res = await getAgent().com.atproto.server.getAccountInviteCodes({})
 
       if (!res.data?.codes) {
         throw new Error(`useInviteCodesQuery: no codes returned`)
diff --git a/src/state/queries/like.ts b/src/state/queries/like.ts
index 187d8fb82..94857eb91 100644
--- a/src/state/queries/like.ts
+++ b/src/state/queries/like.ts
@@ -1,24 +1,20 @@
 import {useMutation} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 
 export function useLikeMutation() {
-  const {agent} = useSession()
-
   return useMutation({
     mutationFn: async ({uri, cid}: {uri: string; cid: string}) => {
-      const res = await agent.like(uri, cid)
+      const res = await getAgent().like(uri, cid)
       return {uri: res.uri}
     },
   })
 }
 
 export function useUnlikeMutation() {
-  const {agent} = useSession()
-
   return useMutation({
     mutationFn: async ({uri}: {uri: string}) => {
-      await agent.deleteLike(uri)
+      await getAgent().deleteLike(uri)
     },
   })
 }
diff --git a/src/state/queries/list-members.ts b/src/state/queries/list-members.ts
index ae932462d..7aa91b1dc 100644
--- a/src/state/queries/list-members.ts
+++ b/src/state/queries/list-members.ts
@@ -1,7 +1,7 @@
 import {AppBskyGraphGetList} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -10,7 +10,6 @@ type RQPageParam = string | undefined
 export const RQKEY = (uri: string) => ['list-members', uri]
 
 export function useListMembersQuery(uri: string) {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyGraphGetList.OutputSchema,
     Error,
@@ -21,7 +20,7 @@ export function useListMembersQuery(uri: string) {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(uri),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.graph.getList({
+      const res = await getAgent().app.bsky.graph.getList({
         list: uri,
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/list-memberships.ts b/src/state/queries/list-memberships.ts
index 7ab29d180..6cae3fa2e 100644
--- a/src/state/queries/list-memberships.ts
+++ b/src/state/queries/list-memberships.ts
@@ -17,7 +17,7 @@
 import {AtUri} from '@atproto/api'
 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {useSession, getAgent} from '#/state/session'
 import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members'
 import {STALE} from '#/state/queries'
 
@@ -38,7 +38,7 @@ export interface ListMembersip {
  * This API is dangerous! Read the note above!
  */
 export function useDangerousListMembershipsQuery() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   return useQuery<ListMembersip[]>({
     staleTime: STALE.MINUTES.FIVE,
     queryKey: RQKEY(),
@@ -49,7 +49,7 @@ export function useDangerousListMembershipsQuery() {
       let cursor
       let arr: ListMembersip[] = []
       for (let i = 0; i < SANITY_PAGE_LIMIT; i++) {
-        const res = await agent.app.bsky.graph.listitem.list({
+        const res = await getAgent().app.bsky.graph.listitem.list({
           repo: currentAccount.did,
           limit: PAGE_SIZE,
           cursor,
@@ -89,7 +89,7 @@ export function getMembership(
 }
 
 export function useListMembershipAddMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const queryClient = useQueryClient()
   return useMutation<
     {uri: string; cid: string},
@@ -100,7 +100,7 @@ export function useListMembershipAddMutation() {
       if (!currentAccount) {
         throw new Error('Not logged in')
       }
-      const res = await agent.app.bsky.graph.listitem.create(
+      const res = await getAgent().app.bsky.graph.listitem.create(
         {repo: currentAccount.did},
         {
           subject: actorDid,
@@ -147,7 +147,7 @@ export function useListMembershipAddMutation() {
 }
 
 export function useListMembershipRemoveMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const queryClient = useQueryClient()
   return useMutation<
     void,
@@ -159,7 +159,7 @@ export function useListMembershipRemoveMutation() {
         throw new Error('Not logged in')
       }
       const membershipUrip = new AtUri(membershipUri)
-      await agent.app.bsky.graph.listitem.delete({
+      await getAgent().app.bsky.graph.listitem.delete({
         repo: currentAccount.did,
         rkey: membershipUrip.rkey,
       })
diff --git a/src/state/queries/list.ts b/src/state/queries/list.ts
index c31afe01b..ef05009d1 100644
--- a/src/state/queries/list.ts
+++ b/src/state/queries/list.ts
@@ -8,7 +8,7 @@ import {
 import {Image as RNImage} from 'react-native-image-crop-picker'
 import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
 import chunk from 'lodash.chunk'
-import {useSession} from '../session'
+import {useSession, getAgent} from '../session'
 import {invalidate as invalidateMyLists} from './my-lists'
 import {RQKEY as PROFILE_LISTS_RQKEY} from './profile-lists'
 import {uploadBlob} from '#/lib/api'
@@ -18,7 +18,6 @@ import {STALE} from '#/state/queries'
 export const RQKEY = (uri: string) => ['list', uri]
 
 export function useListQuery(uri?: string) {
-  const {agent} = useSession()
   return useQuery<AppBskyGraphDefs.ListView, Error>({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(uri || ''),
@@ -26,7 +25,7 @@ export function useListQuery(uri?: string) {
       if (!uri) {
         throw new Error('URI not provided')
       }
-      const res = await agent.app.bsky.graph.getList({
+      const res = await getAgent().app.bsky.graph.getList({
         list: uri,
         limit: 1,
       })
@@ -43,7 +42,7 @@ export interface ListCreateMutateParams {
   avatar: RNImage | null | undefined
 }
 export function useListCreateMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const queryClient = useQueryClient()
   return useMutation<{uri: string; cid: string}, Error, ListCreateMutateParams>(
     {
@@ -65,10 +64,10 @@ export function useListCreateMutation() {
           createdAt: new Date().toISOString(),
         }
         if (avatar) {
-          const blobRes = await uploadBlob(agent, avatar.path, avatar.mime)
+          const blobRes = await uploadBlob(getAgent(), avatar.path, avatar.mime)
           record.avatar = blobRes.data.blob
         }
-        const res = await agent.app.bsky.graph.list.create(
+        const res = await getAgent().app.bsky.graph.list.create(
           {
             repo: currentAccount.did,
           },
@@ -77,7 +76,7 @@ export function useListCreateMutation() {
 
         // wait for the appview to update
         await whenAppViewReady(
-          agent,
+          getAgent(),
           res.uri,
           (v: AppBskyGraphGetList.Response) => {
             return typeof v?.data?.list.uri === 'string'
@@ -102,7 +101,7 @@ export interface ListMetadataMutateParams {
   avatar: RNImage | null | undefined
 }
 export function useListMetadataMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const queryClient = useQueryClient()
   return useMutation<
     {uri: string; cid: string},
@@ -119,7 +118,7 @@ export function useListMetadataMutation() {
       }
 
       // get the current record
-      const {value: record} = await agent.app.bsky.graph.list.get({
+      const {value: record} = await getAgent().app.bsky.graph.list.get({
         repo: currentAccount.did,
         rkey,
       })
@@ -128,13 +127,13 @@ export function useListMetadataMutation() {
       record.name = name
       record.description = description
       if (avatar) {
-        const blobRes = await uploadBlob(agent, avatar.path, avatar.mime)
+        const blobRes = await uploadBlob(getAgent(), avatar.path, avatar.mime)
         record.avatar = blobRes.data.blob
       } else if (avatar === null) {
         record.avatar = undefined
       }
       const res = (
-        await agent.com.atproto.repo.putRecord({
+        await getAgent().com.atproto.repo.putRecord({
           repo: currentAccount.did,
           collection: 'app.bsky.graph.list',
           rkey,
@@ -144,7 +143,7 @@ export function useListMetadataMutation() {
 
       // wait for the appview to update
       await whenAppViewReady(
-        agent,
+        getAgent(),
         res.uri,
         (v: AppBskyGraphGetList.Response) => {
           const list = v.data.list
@@ -168,7 +167,7 @@ export function useListMetadataMutation() {
 }
 
 export function useListDeleteMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, {uri: string}>({
     mutationFn: async ({uri}) => {
@@ -179,7 +178,7 @@ export function useListDeleteMutation() {
       let cursor
       let listitemRecordUris: string[] = []
       for (let i = 0; i < 100; i++) {
-        const res = await agent.app.bsky.graph.listitem.list({
+        const res = await getAgent().app.bsky.graph.listitem.list({
           repo: currentAccount.did,
           cursor,
           limit: 100,
@@ -210,16 +209,20 @@ export function useListDeleteMutation() {
 
       // apply in chunks
       for (const writesChunk of chunk(writes, 10)) {
-        await agent.com.atproto.repo.applyWrites({
+        await getAgent().com.atproto.repo.applyWrites({
           repo: currentAccount.did,
           writes: writesChunk,
         })
       }
 
       // wait for the appview to update
-      await whenAppViewReady(agent, uri, (v: AppBskyGraphGetList.Response) => {
-        return !v?.success
-      })
+      await whenAppViewReady(
+        getAgent(),
+        uri,
+        (v: AppBskyGraphGetList.Response) => {
+          return !v?.success
+        },
+      )
     },
     onSuccess() {
       invalidateMyLists(queryClient)
@@ -232,14 +235,13 @@ export function useListDeleteMutation() {
 }
 
 export function useListMuteMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, {uri: string; mute: boolean}>({
     mutationFn: async ({uri, mute}) => {
       if (mute) {
-        await agent.muteModList(uri)
+        await getAgent().muteModList(uri)
       } else {
-        await agent.unmuteModList(uri)
+        await getAgent().unmuteModList(uri)
       }
     },
     onSuccess(data, variables) {
@@ -251,14 +253,13 @@ export function useListMuteMutation() {
 }
 
 export function useListBlockMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, {uri: string; block: boolean}>({
     mutationFn: async ({uri, block}) => {
       if (block) {
-        await agent.blockModList(uri)
+        await getAgent().blockModList(uri)
       } else {
-        await agent.unblockModList(uri)
+        await getAgent().unblockModList(uri)
       }
     },
     onSuccess(data, variables) {
diff --git a/src/state/queries/my-blocked-accounts.ts b/src/state/queries/my-blocked-accounts.ts
index 5a83bee2c..4d5bd7a0e 100644
--- a/src/state/queries/my-blocked-accounts.ts
+++ b/src/state/queries/my-blocked-accounts.ts
@@ -1,14 +1,13 @@
 import {AppBskyGraphGetBlocks} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 export const RQKEY = () => ['my-blocked-accounts']
 type RQPageParam = string | undefined
 
 export function useMyBlockedAccountsQuery() {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyGraphGetBlocks.OutputSchema,
     Error,
@@ -19,7 +18,7 @@ export function useMyBlockedAccountsQuery() {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.graph.getBlocks({
+      const res = await getAgent().app.bsky.graph.getBlocks({
         limit: 30,
         cursor: pageParam,
       })
diff --git a/src/state/queries/my-follows.ts b/src/state/queries/my-follows.ts
index 64966ca81..f95c3f5a7 100644
--- a/src/state/queries/my-follows.ts
+++ b/src/state/queries/my-follows.ts
@@ -1,6 +1,6 @@
 import {AppBskyActorDefs} from '@atproto/api'
 import {useQuery} from '@tanstack/react-query'
-import {useSession} from '../session'
+import {useSession, getAgent} from '../session'
 import {STALE} from '#/state/queries'
 
 // sanity limit is SANITY_PAGE_LIMIT*PAGE_SIZE total records
@@ -11,7 +11,7 @@ const PAGE_SIZE = 100
 export const RQKEY = () => ['my-follows']
 
 export function useMyFollowsQuery() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(),
@@ -22,7 +22,7 @@ export function useMyFollowsQuery() {
       let cursor
       let arr: AppBskyActorDefs.ProfileViewBasic[] = []
       for (let i = 0; i < SANITY_PAGE_LIMIT; i++) {
-        const res = await agent.getFollows({
+        const res = await getAgent().getFollows({
           actor: currentAccount.did,
           cursor,
           limit: PAGE_SIZE,
diff --git a/src/state/queries/my-lists.ts b/src/state/queries/my-lists.ts
index 0b049e65f..3265cb21e 100644
--- a/src/state/queries/my-lists.ts
+++ b/src/state/queries/my-lists.ts
@@ -2,14 +2,14 @@ import {AppBskyGraphDefs} from '@atproto/api'
 import {useQuery, QueryClient} from '@tanstack/react-query'
 
 import {accumulate} from '#/lib/async/accumulate'
-import {useSession} from '#/state/session'
+import {useSession, getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 export type MyListsFilter = 'all' | 'curate' | 'mod'
 export const RQKEY = (filter: MyListsFilter) => ['my-lists', filter]
 
 export function useMyListsQuery(filter: MyListsFilter) {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   return useQuery<AppBskyGraphDefs.ListView[]>({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(filter),
@@ -17,8 +17,8 @@ export function useMyListsQuery(filter: MyListsFilter) {
       let lists: AppBskyGraphDefs.ListView[] = []
       const promises = [
         accumulate(cursor =>
-          agent.app.bsky.graph
-            .getLists({
+          getAgent()
+            .app.bsky.graph.getLists({
               actor: currentAccount!.did,
               cursor,
               limit: 50,
@@ -32,8 +32,8 @@ export function useMyListsQuery(filter: MyListsFilter) {
       if (filter === 'all' || filter === 'mod') {
         promises.push(
           accumulate(cursor =>
-            agent.app.bsky.graph
-              .getListMutes({
+            getAgent()
+              .app.bsky.graph.getListMutes({
                 cursor,
                 limit: 50,
               })
@@ -45,8 +45,8 @@ export function useMyListsQuery(filter: MyListsFilter) {
         )
         promises.push(
           accumulate(cursor =>
-            agent.app.bsky.graph
-              .getListBlocks({
+            getAgent()
+              .app.bsky.graph.getListBlocks({
                 cursor,
                 limit: 50,
               })
diff --git a/src/state/queries/my-muted-accounts.ts b/src/state/queries/my-muted-accounts.ts
index c46474b27..1d686637a 100644
--- a/src/state/queries/my-muted-accounts.ts
+++ b/src/state/queries/my-muted-accounts.ts
@@ -1,14 +1,13 @@
 import {AppBskyGraphGetMutes} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 export const RQKEY = () => ['my-muted-accounts']
 type RQPageParam = string | undefined
 
 export function useMyMutedAccountsQuery() {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyGraphGetMutes.OutputSchema,
     Error,
@@ -19,7 +18,7 @@ export function useMyMutedAccountsQuery() {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.graph.getMutes({
+      const res = await getAgent().app.bsky.graph.getMutes({
         limit: 30,
         cursor: pageParam,
       })
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts
index c1d9edb44..a47349827 100644
--- a/src/state/queries/notifications/feed.ts
+++ b/src/state/queries/notifications/feed.ts
@@ -8,7 +8,7 @@ import {
 } from '@atproto/api'
 import chunk from 'lodash.chunk'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
-import {useSession} from '../../session'
+import {getAgent} from '../../session'
 import {useModerationOpts} from '../preferences'
 import {shouldFilterNotif} from './util'
 import {useMutedThreads} from '#/state/muted-threads'
@@ -49,7 +49,6 @@ export interface FeedPage {
 }
 
 export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
-  const {agent} = useSession()
   const moderationOpts = useModerationOpts()
   const threadMutes = useMutedThreads()
   const enabled = opts?.enabled !== false
@@ -64,7 +63,7 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
     staleTime: STALE.INFINITY,
     queryKey: RQKEY(),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.listNotifications({
+      const res = await getAgent().listNotifications({
         limit: PAGE_SIZE,
         cursor: pageParam,
       })
@@ -79,7 +78,7 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
 
       // we fetch subjects of notifications (usually posts) now instead of lazily
       // in the UI to avoid relayouts
-      const subjects = await fetchSubjects(agent, notifsGrouped)
+      const subjects = await fetchSubjects(getAgent(), notifsGrouped)
       for (const notif of notifsGrouped) {
         if (notif.subjectUri) {
           notif.subject = subjects.get(notif.subjectUri)
diff --git a/src/state/queries/notifications/unread.tsx b/src/state/queries/notifications/unread.tsx
index 91aa6f3c2..80b12112e 100644
--- a/src/state/queries/notifications/unread.tsx
+++ b/src/state/queries/notifications/unread.tsx
@@ -1,7 +1,7 @@
 import React from 'react'
 import * as Notifications from 'expo-notifications'
 import BroadcastChannel from '#/lib/broadcast'
-import {useSession} from '#/state/session'
+import {useSession, getAgent} from '#/state/session'
 import {useModerationOpts} from '../preferences'
 import {shouldFilterNotif} from './util'
 import {isNative} from '#/platform/detection'
@@ -25,7 +25,7 @@ const apiContext = React.createContext<ApiContext>({
 })
 
 export function Provider({children}: React.PropsWithChildren<{}>) {
-  const {hasSession, agent} = useSession()
+  const {hasSession} = useSession()
   const moderationOpts = useModerationOpts()
 
   const [numUnread, setNumUnread] = React.useState('')
@@ -60,7 +60,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
     return {
       async markAllRead() {
         // update server
-        await agent.updateSeenNotifications(lastSyncRef.current.toISOString())
+        await getAgent().updateSeenNotifications(
+          lastSyncRef.current.toISOString(),
+        )
 
         // update & broadcast
         setNumUnread('')
@@ -69,7 +71,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
 
       async checkUnread() {
         // count
-        const res = await agent.listNotifications({limit: 40})
+        const res = await getAgent().listNotifications({limit: 40})
         const filtered = res.data.notifications.filter(
           notif => !notif.isRead && !shouldFilterNotif(notif, moderationOpts),
         )
@@ -94,7 +96,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
         broadcast.postMessage({event: num})
       },
     }
-  }, [setNumUnread, agent, moderationOpts])
+  }, [setNumUnread, moderationOpts])
   checkUnreadRef.current = api.checkUnread
 
   return (
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 17cd1abb6..5f81cb44d 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -1,7 +1,7 @@
 import {useCallback, useMemo} from 'react'
 import {AppBskyFeedDefs, AppBskyFeedPost, moderatePost} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
-import {useSession} from '../session'
+import {getAgent} from '../session'
 import {useFeedTuners} from '../preferences/feed-tuners'
 import {FeedTuner, NoopFeedTuner} from 'lib/api/feed-manip'
 import {FeedAPI, ReasonFeedSource} from 'lib/api/feed/types'
@@ -66,10 +66,10 @@ export function usePostFeedQuery(
   params?: FeedParams,
   opts?: {enabled?: boolean},
 ) {
-  const {agent} = useSession()
   const feedTuners = useFeedTuners(feedDesc)
   const enabled = opts?.enabled !== false
   const moderationOpts = useModerationOpts()
+  const agent = getAgent()
 
   const api: FeedAPI = useMemo(() => {
     if (feedDesc === 'home') {
diff --git a/src/state/queries/post-liked-by.ts b/src/state/queries/post-liked-by.ts
index 7a2161359..33b379a0c 100644
--- a/src/state/queries/post-liked-by.ts
+++ b/src/state/queries/post-liked-by.ts
@@ -1,7 +1,7 @@
 import {AppBskyFeedGetLikes} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -11,7 +11,6 @@ type RQPageParam = string | undefined
 export const RQKEY = (resolvedUri: string) => ['post-liked-by', resolvedUri]
 
 export function usePostLikedByQuery(resolvedUri: string | undefined) {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyFeedGetLikes.OutputSchema,
     Error,
@@ -22,7 +21,7 @@ export function usePostLikedByQuery(resolvedUri: string | undefined) {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(resolvedUri || ''),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.getLikes({
+      const res = await getAgent().getLikes({
         uri: resolvedUri || '',
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/post-reposted-by.ts b/src/state/queries/post-reposted-by.ts
index 7b2f40417..3a6fe1633 100644
--- a/src/state/queries/post-reposted-by.ts
+++ b/src/state/queries/post-reposted-by.ts
@@ -1,7 +1,7 @@
 import {AppBskyFeedGetRepostedBy} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -11,7 +11,6 @@ type RQPageParam = string | undefined
 export const RQKEY = (resolvedUri: string) => ['post-reposted-by', resolvedUri]
 
 export function usePostRepostedByQuery(resolvedUri: string | undefined) {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyFeedGetRepostedBy.OutputSchema,
     Error,
@@ -22,7 +21,7 @@ export function usePostRepostedByQuery(resolvedUri: string | undefined) {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(resolvedUri || ''),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.getRepostedBy({
+      const res = await getAgent().getRepostedBy({
         uri: resolvedUri || '',
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index b22b0aa35..3c6989466 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -5,7 +5,7 @@ import {
 } from '@atproto/api'
 import {useQuery} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
 import {STALE} from '#/state/queries'
 
@@ -58,12 +58,11 @@ export type ThreadNode =
   | ThreadUnknown
 
 export function usePostThreadQuery(uri: string | undefined) {
-  const {agent} = useSession()
   return useQuery<ThreadNode, Error>({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(uri || ''),
     async queryFn() {
-      const res = await agent.getPostThread({uri: uri!})
+      const res = await getAgent().getPostThread({uri: uri!})
       if (res.success) {
         return responseToThreadNodes(res.data.thread)
       }
diff --git a/src/state/queries/post.ts b/src/state/queries/post.ts
index 73d94f434..d4193b8ce 100644
--- a/src/state/queries/post.ts
+++ b/src/state/queries/post.ts
@@ -2,19 +2,18 @@ import React from 'react'
 import {AppBskyFeedDefs, AtUri} from '@atproto/api'
 import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {updatePostShadow} from '#/state/cache/post-shadow'
 import {STALE} from '#/state/queries'
 
 export const RQKEY = (postUri: string) => ['post', postUri]
 
 export function usePostQuery(uri: string | undefined) {
-  const {agent} = useSession()
   return useQuery<AppBskyFeedDefs.PostView>({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(uri || ''),
     async queryFn() {
-      const res = await agent.getPosts({uris: [uri!]})
+      const res = await getAgent().getPosts({uris: [uri!]})
       if (res.success && res.data.posts[0]) {
         return res.data.posts[0]
       }
@@ -27,7 +26,6 @@ export function usePostQuery(uri: string | undefined) {
 
 export function useGetPost() {
   const queryClient = useQueryClient()
-  const {agent} = useSession()
   return React.useCallback(
     async ({uri}: {uri: string}) => {
       return queryClient.fetchQuery({
@@ -37,13 +35,13 @@ export function useGetPost() {
           const urip = new AtUri(uri)
 
           if (!urip.host.startsWith('did:')) {
-            const res = await agent.resolveHandle({
+            const res = await getAgent().resolveHandle({
               handle: urip.host,
             })
             urip.host = res.data.did
           }
 
-          const res = await agent.getPosts({
+          const res = await getAgent().getPosts({
             uris: [urip.toString()!],
           })
 
@@ -55,18 +53,17 @@ export function useGetPost() {
         },
       })
     },
-    [agent, queryClient],
+    [queryClient],
   )
 }
 
 export function usePostLikeMutation() {
-  const {agent} = useSession()
   return useMutation<
     {uri: string}, // responds with the uri of the like
     Error,
     {uri: string; cid: string; likeCount: number} // the post's uri, cid, and likes
   >({
-    mutationFn: post => agent.like(post.uri, post.cid),
+    mutationFn: post => getAgent().like(post.uri, post.cid),
     onMutate(variables) {
       // optimistically update the post-shadow
       updatePostShadow(variables.uri, {
@@ -91,14 +88,13 @@ export function usePostLikeMutation() {
 }
 
 export function usePostUnlikeMutation() {
-  const {agent} = useSession()
   return useMutation<
     void,
     Error,
     {postUri: string; likeUri: string; likeCount: number}
   >({
     mutationFn: async ({likeUri}) => {
-      await agent.deleteLike(likeUri)
+      await getAgent().deleteLike(likeUri)
     },
     onMutate(variables) {
       // optimistically update the post-shadow
@@ -118,13 +114,12 @@ export function usePostUnlikeMutation() {
 }
 
 export function usePostRepostMutation() {
-  const {agent} = useSession()
   return useMutation<
     {uri: string}, // responds with the uri of the repost
     Error,
     {uri: string; cid: string; repostCount: number} // the post's uri, cid, and reposts
   >({
-    mutationFn: post => agent.repost(post.uri, post.cid),
+    mutationFn: post => getAgent().repost(post.uri, post.cid),
     onMutate(variables) {
       // optimistically update the post-shadow
       updatePostShadow(variables.uri, {
@@ -149,14 +144,13 @@ export function usePostRepostMutation() {
 }
 
 export function usePostUnrepostMutation() {
-  const {agent} = useSession()
   return useMutation<
     void,
     Error,
     {postUri: string; repostUri: string; repostCount: number}
   >({
     mutationFn: async ({repostUri}) => {
-      await agent.deleteRepost(repostUri)
+      await getAgent().deleteRepost(repostUri)
     },
     onMutate(variables) {
       // optimistically update the post-shadow
@@ -176,10 +170,9 @@ export function usePostUnrepostMutation() {
 }
 
 export function usePostDeleteMutation() {
-  const {agent} = useSession()
   return useMutation<void, Error, {uri: string}>({
     mutationFn: async ({uri}) => {
-      await agent.deletePost(uri)
+      await getAgent().deletePost(uri)
     },
     onSuccess(data, variables) {
       updatePostShadow(variables.uri, {isDeleted: true})
diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts
index 483076431..fe719225d 100644
--- a/src/state/queries/preferences/index.ts
+++ b/src/state/queries/preferences/index.ts
@@ -9,7 +9,7 @@ import isEqual from 'lodash.isequal'
 
 import {track} from '#/lib/analytics/analytics'
 import {getAge} from '#/lib/strings/time'
-import {useSession} from '#/state/session'
+import {useSession, getAgent} from '#/state/session'
 import {DEFAULT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation'
 import {
   ConfigurableLabelGroup,
@@ -31,13 +31,13 @@ export * from '#/state/queries/preferences/const'
 export const usePreferencesQueryKey = ['getPreferences']
 
 export function usePreferencesQuery() {
-  const {agent, hasSession} = useSession()
+  const {hasSession} = useSession()
   return useQuery({
     enabled: hasSession,
     staleTime: STALE.MINUTES.ONE,
     queryKey: usePreferencesQueryKey,
     queryFn: async () => {
-      const res = await agent.getPreferences()
+      const res = await getAgent().getPreferences()
       const preferences: UsePreferencesQueryResponse = {
         ...res,
         feeds: {
@@ -110,12 +110,11 @@ export function useModerationOpts() {
 }
 
 export function useClearPreferencesMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation({
     mutationFn: async () => {
-      await agent.app.bsky.actor.putPreferences({preferences: []})
+      await getAgent().app.bsky.actor.putPreferences({preferences: []})
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -125,7 +124,6 @@ export function useClearPreferencesMutation() {
 }
 
 export function usePreferencesSetContentLabelMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<
@@ -134,7 +132,7 @@ export function usePreferencesSetContentLabelMutation() {
     {labelGroup: ConfigurableLabelGroup; visibility: LabelPreference}
   >({
     mutationFn: async ({labelGroup, visibility}) => {
-      await agent.setContentLabelPref(labelGroup, visibility)
+      await getAgent().setContentLabelPref(labelGroup, visibility)
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -144,12 +142,11 @@ export function usePreferencesSetContentLabelMutation() {
 }
 
 export function usePreferencesSetAdultContentMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, {enabled: boolean}>({
     mutationFn: async ({enabled}) => {
-      await agent.setAdultContentEnabled(enabled)
+      await getAgent().setAdultContentEnabled(enabled)
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -159,12 +156,11 @@ export function usePreferencesSetAdultContentMutation() {
 }
 
 export function usePreferencesSetBirthDateMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, {birthDate: Date}>({
     mutationFn: async ({birthDate}: {birthDate: Date}) => {
-      await agent.setPersonalDetails({birthDate})
+      await getAgent().setPersonalDetails({birthDate})
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -174,12 +170,11 @@ export function usePreferencesSetBirthDateMutation() {
 }
 
 export function useSetFeedViewPreferencesMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, Partial<BskyFeedViewPreference>>({
     mutationFn: async prefs => {
-      await agent.setFeedViewPrefs('home', prefs)
+      await getAgent().setFeedViewPrefs('home', prefs)
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -189,12 +184,11 @@ export function useSetFeedViewPreferencesMutation() {
 }
 
 export function useSetThreadViewPreferencesMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, Partial<ThreadViewPreferences>>({
     mutationFn: async prefs => {
-      await agent.setThreadViewPrefs(prefs)
+      await getAgent().setThreadViewPrefs(prefs)
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -204,7 +198,6 @@ export function useSetThreadViewPreferencesMutation() {
 }
 
 export function useSetSaveFeedsMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<
@@ -213,7 +206,7 @@ export function useSetSaveFeedsMutation() {
     Pick<UsePreferencesQueryResponse['feeds'], 'saved' | 'pinned'>
   >({
     mutationFn: async ({saved, pinned}) => {
-      await agent.setSavedFeeds(saved, pinned)
+      await getAgent().setSavedFeeds(saved, pinned)
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: usePreferencesQueryKey,
@@ -223,12 +216,11 @@ export function useSetSaveFeedsMutation() {
 }
 
 export function useSaveFeedMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, {uri: string}>({
     mutationFn: async ({uri}) => {
-      await agent.addSavedFeed(uri)
+      await getAgent().addSavedFeed(uri)
       track('CustomFeed:Save')
       // triggers a refetch
       await queryClient.invalidateQueries({
@@ -239,12 +231,11 @@ export function useSaveFeedMutation() {
 }
 
 export function useRemoveFeedMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, {uri: string}>({
     mutationFn: async ({uri}) => {
-      await agent.removeSavedFeed(uri)
+      await getAgent().removeSavedFeed(uri)
       track('CustomFeed:Unsave')
       // triggers a refetch
       await queryClient.invalidateQueries({
@@ -255,12 +246,11 @@ export function useRemoveFeedMutation() {
 }
 
 export function usePinFeedMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, {uri: string}>({
     mutationFn: async ({uri}) => {
-      await agent.addPinnedFeed(uri)
+      await getAgent().addPinnedFeed(uri)
       track('CustomFeed:Pin', {uri})
       // triggers a refetch
       await queryClient.invalidateQueries({
@@ -271,12 +261,11 @@ export function usePinFeedMutation() {
 }
 
 export function useUnpinFeedMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return useMutation<void, unknown, {uri: string}>({
     mutationFn: async ({uri}) => {
-      await agent.removePinnedFeed(uri)
+      await getAgent().removePinnedFeed(uri)
       track('CustomFeed:Unpin', {uri})
       // triggers a refetch
       await queryClient.invalidateQueries({
diff --git a/src/state/queries/profile-extra-info.ts b/src/state/queries/profile-extra-info.ts
index 4e7890e32..8fc32c33e 100644
--- a/src/state/queries/profile-extra-info.ts
+++ b/src/state/queries/profile-extra-info.ts
@@ -1,6 +1,6 @@
 import {useQuery} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 // TODO refactor invalidate on mutate?
@@ -11,17 +11,16 @@ export const RQKEY = (did: string) => ['profile-extra-info', did]
  * is not available in the API's ProfileView
  */
 export function useProfileExtraInfoQuery(did: string) {
-  const {agent} = useSession()
   return useQuery({
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(did),
     async queryFn() {
       const [listsRes, feedsRes] = await Promise.all([
-        agent.app.bsky.graph.getLists({
+        getAgent().app.bsky.graph.getLists({
           actor: did,
           limit: 1,
         }),
-        agent.app.bsky.feed.getActorFeeds({
+        getAgent().app.bsky.feed.getActorFeeds({
           actor: did,
           limit: 1,
         }),
diff --git a/src/state/queries/profile-feedgens.ts b/src/state/queries/profile-feedgens.ts
index 9f8033065..04860430e 100644
--- a/src/state/queries/profile-feedgens.ts
+++ b/src/state/queries/profile-feedgens.ts
@@ -1,7 +1,7 @@
 import {AppBskyFeedGetActorFeeds} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -14,7 +14,6 @@ export function useProfileFeedgensQuery(
   did: string,
   opts?: {enabled?: boolean},
 ) {
-  const {agent} = useSession()
   const enabled = opts?.enabled !== false
   return useInfiniteQuery<
     AppBskyFeedGetActorFeeds.OutputSchema,
@@ -26,7 +25,7 @@ export function useProfileFeedgensQuery(
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(did),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.feed.getActorFeeds({
+      const res = await getAgent().app.bsky.feed.getActorFeeds({
         actor: did,
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/profile-followers.ts b/src/state/queries/profile-followers.ts
index dbad57486..774bd23f1 100644
--- a/src/state/queries/profile-followers.ts
+++ b/src/state/queries/profile-followers.ts
@@ -1,7 +1,7 @@
 import {AppBskyGraphGetFollowers} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -10,7 +10,6 @@ type RQPageParam = string | undefined
 export const RQKEY = (did: string) => ['profile-followers', did]
 
 export function useProfileFollowersQuery(did: string | undefined) {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyGraphGetFollowers.OutputSchema,
     Error,
@@ -21,7 +20,7 @@ export function useProfileFollowersQuery(did: string | undefined) {
     staleTime: STALE.MINUTES.FIVE,
     queryKey: RQKEY(did || ''),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.graph.getFollowers({
+      const res = await getAgent().app.bsky.graph.getFollowers({
         actor: did || '',
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/profile-follows.ts b/src/state/queries/profile-follows.ts
index 71c51993d..8af1fba07 100644
--- a/src/state/queries/profile-follows.ts
+++ b/src/state/queries/profile-follows.ts
@@ -1,7 +1,7 @@
 import {AppBskyGraphGetFollows} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -11,7 +11,6 @@ type RQPageParam = string | undefined
 export const RQKEY = (did: string) => ['profile-follows', did]
 
 export function useProfileFollowsQuery(did: string | undefined) {
-  const {agent} = useSession()
   return useInfiniteQuery<
     AppBskyGraphGetFollows.OutputSchema,
     Error,
@@ -22,7 +21,7 @@ export function useProfileFollowsQuery(did: string | undefined) {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(did || ''),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.graph.getFollows({
+      const res = await getAgent().app.bsky.graph.getFollows({
         actor: did || '',
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/profile-lists.ts b/src/state/queries/profile-lists.ts
index 919ac1153..997c85910 100644
--- a/src/state/queries/profile-lists.ts
+++ b/src/state/queries/profile-lists.ts
@@ -1,7 +1,7 @@
 import {AppBskyGraphGetLists} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 const PAGE_SIZE = 30
@@ -10,7 +10,6 @@ type RQPageParam = string | undefined
 export const RQKEY = (did: string) => ['profile-lists', did]
 
 export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
-  const {agent} = useSession()
   const enabled = opts?.enabled !== false
   return useInfiniteQuery<
     AppBskyGraphGetLists.OutputSchema,
@@ -22,7 +21,7 @@ export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
     staleTime: STALE.MINUTES.ONE,
     queryKey: RQKEY(did),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
-      const res = await agent.app.bsky.graph.getLists({
+      const res = await getAgent().app.bsky.graph.getLists({
         actor: did,
         limit: PAGE_SIZE,
         cursor: pageParam,
diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts
index 9805c2713..e27bac9a6 100644
--- a/src/state/queries/profile.ts
+++ b/src/state/queries/profile.ts
@@ -8,7 +8,7 @@ import {
 } from '@atproto/api'
 import {useQuery, useQueryClient, useMutation} from '@tanstack/react-query'
 import {Image as RNImage} from 'react-native-image-crop-picker'
-import {useSession} from '../session'
+import {useSession, getAgent} from '../session'
 import {updateProfileShadow} from '../cache/profile-shadow'
 import {uploadBlob} from '#/lib/api'
 import {until} from '#/lib/async/until'
@@ -21,12 +21,11 @@ import {STALE} from '#/state/queries'
 export const RQKEY = (did: string) => ['profile', did]
 
 export function useProfileQuery({did}: {did: string | undefined}) {
-  const {agent} = useSession()
   return useQuery({
     staleTime: STALE.MINUTES.FIVE,
     queryKey: RQKEY(did || ''),
     queryFn: async () => {
-      const res = await agent.getProfile({actor: did || ''})
+      const res = await getAgent().getProfile({actor: did || ''})
       return res.data
     },
     enabled: !!did,
@@ -40,17 +39,16 @@ interface ProfileUpdateParams {
   newUserBanner: RNImage | undefined | null
 }
 export function useProfileUpdateMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, ProfileUpdateParams>({
     mutationFn: async ({profile, updates, newUserAvatar, newUserBanner}) => {
-      await agent.upsertProfile(async existing => {
+      await getAgent().upsertProfile(async existing => {
         existing = existing || {}
         existing.displayName = updates.displayName
         existing.description = updates.description
         if (newUserAvatar) {
           const res = await uploadBlob(
-            agent,
+            getAgent(),
             newUserAvatar.path,
             newUserAvatar.mime,
           )
@@ -60,7 +58,7 @@ export function useProfileUpdateMutation() {
         }
         if (newUserBanner) {
           const res = await uploadBlob(
-            agent,
+            getAgent(),
             newUserBanner.path,
             newUserBanner.mime,
           )
@@ -70,7 +68,7 @@ export function useProfileUpdateMutation() {
         }
         return existing
       })
-      await whenAppViewReady(agent, profile.did, res => {
+      await whenAppViewReady(getAgent(), profile.did, res => {
         if (typeof newUserAvatar !== 'undefined') {
           if (newUserAvatar === null && res.data.avatar) {
             // url hasnt cleared yet
@@ -160,14 +158,13 @@ export function useProfileFollowMutationQueue(
 }
 
 function useProfileFollowMutation() {
-  const {agent} = useSession()
   return useMutation<
     {uri: string; cid: string},
     Error,
     {did: string; skipOptimistic?: boolean}
   >({
     mutationFn: async ({did}) => {
-      return await agent.follow(did)
+      return await getAgent().follow(did)
     },
     onMutate(variables) {
       if (!variables.skipOptimistic) {
@@ -197,14 +194,13 @@ function useProfileFollowMutation() {
 }
 
 function useProfileUnfollowMutation() {
-  const {agent} = useSession()
   return useMutation<
     void,
     Error,
     {did: string; followUri: string; skipOptimistic?: boolean}
   >({
     mutationFn: async ({followUri}) => {
-      return await agent.deleteFollow(followUri)
+      return await getAgent().deleteFollow(followUri)
     },
     onMutate(variables) {
       if (!variables.skipOptimistic) {
@@ -276,11 +272,10 @@ export function useProfileMuteMutationQueue(
 }
 
 function useProfileMuteMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, {did: string; skipOptimistic?: boolean}>({
     mutationFn: async ({did}) => {
-      await agent.mute(did)
+      await getAgent().mute(did)
     },
     onMutate(variables) {
       if (!variables.skipOptimistic) {
@@ -305,11 +300,10 @@ function useProfileMuteMutation() {
 }
 
 function useProfileUnmuteMutation() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
   return useMutation<void, Error, {did: string; skipOptimistic?: boolean}>({
     mutationFn: async ({did}) => {
-      await agent.unmute(did)
+      await getAgent().unmute(did)
     },
     onMutate(variables) {
       if (!variables.skipOptimistic) {
@@ -389,7 +383,7 @@ export function useProfileBlockMutationQueue(
 }
 
 function useProfileBlockMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const queryClient = useQueryClient()
   return useMutation<
     {uri: string; cid: string},
@@ -400,7 +394,7 @@ function useProfileBlockMutation() {
       if (!currentAccount) {
         throw new Error('Not signed in')
       }
-      return await agent.app.bsky.graph.block.create(
+      return await getAgent().app.bsky.graph.block.create(
         {repo: currentAccount.did},
         {subject: did, createdAt: new Date().toISOString()},
       )
@@ -434,7 +428,7 @@ function useProfileBlockMutation() {
 }
 
 function useProfileUnblockMutation() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   return useMutation<
     void,
     Error,
@@ -445,7 +439,7 @@ function useProfileUnblockMutation() {
         throw new Error('Not signed in')
       }
       const {rkey} = new AtUri(blockUri)
-      await agent.app.bsky.graph.block.delete({
+      await getAgent().app.bsky.graph.block.delete({
         repo: currentAccount.did,
         rkey,
       })
diff --git a/src/state/queries/resolve-uri.ts b/src/state/queries/resolve-uri.ts
index 370f2a5b6..dc8e7fbe1 100644
--- a/src/state/queries/resolve-uri.ts
+++ b/src/state/queries/resolve-uri.ts
@@ -1,20 +1,19 @@
 import {useQuery} from '@tanstack/react-query'
 import {AtUri} from '@atproto/api'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 export const RQKEY = (uri: string) => ['resolved-uri', uri]
 
 export function useResolveUriQuery(uri: string | undefined) {
-  const {agent} = useSession()
   return useQuery<{uri: string; did: string}, Error>({
     staleTime: STALE.INFINITY,
     queryKey: RQKEY(uri || ''),
     async queryFn() {
       const urip = new AtUri(uri || '')
       if (!urip.host.startsWith('did:')) {
-        const res = await agent.resolveHandle({handle: urip.host})
+        const res = await getAgent().resolveHandle({handle: urip.host})
         urip.host = res.data.did
       }
       return {did: urip.host, uri: urip.toString()}
diff --git a/src/state/queries/search-posts.ts b/src/state/queries/search-posts.ts
index ab6ed4d41..03f3ba339 100644
--- a/src/state/queries/search-posts.ts
+++ b/src/state/queries/search-posts.ts
@@ -1,7 +1,7 @@
 import {AppBskyFeedSearchPosts} from '@atproto/api'
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 
 const searchPostsQueryKey = ({query}: {query: string}) => [
   'search-posts',
@@ -9,8 +9,6 @@ const searchPostsQueryKey = ({query}: {query: string}) => [
 ]
 
 export function useSearchPostsQuery({query}: {query: string}) {
-  const {agent} = useSession()
-
   return useInfiniteQuery<
     AppBskyFeedSearchPosts.OutputSchema,
     Error,
@@ -20,7 +18,7 @@ export function useSearchPostsQuery({query}: {query: string}) {
   >({
     queryKey: searchPostsQueryKey({query}),
     queryFn: async () => {
-      const res = await agent.app.bsky.feed.searchPosts({
+      const res = await getAgent().app.bsky.feed.searchPosts({
         q: query,
         limit: 25,
       })
diff --git a/src/state/queries/suggested-feeds.ts b/src/state/queries/suggested-feeds.ts
index 7e443028d..7e6b534ad 100644
--- a/src/state/queries/suggested-feeds.ts
+++ b/src/state/queries/suggested-feeds.ts
@@ -1,14 +1,12 @@
 import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 import {AppBskyFeedGetSuggestedFeeds} from '@atproto/api'
 
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
 
 export const suggestedFeedsQueryKey = ['suggestedFeeds']
 
 export function useSuggestedFeedsQuery() {
-  const {agent} = useSession()
-
   return useInfiniteQuery<
     AppBskyFeedGetSuggestedFeeds.OutputSchema,
     Error,
@@ -19,7 +17,7 @@ export function useSuggestedFeedsQuery() {
     staleTime: STALE.HOURS.ONE,
     queryKey: suggestedFeedsQueryKey,
     queryFn: async ({pageParam}) => {
-      const res = await agent.app.bsky.feed.getSuggestedFeeds({
+      const res = await getAgent().app.bsky.feed.getSuggestedFeeds({
         limit: 10,
         cursor: pageParam,
       })
diff --git a/src/state/queries/suggested-follows.ts b/src/state/queries/suggested-follows.ts
index b5bf920b3..176bbe15b 100644
--- a/src/state/queries/suggested-follows.ts
+++ b/src/state/queries/suggested-follows.ts
@@ -12,7 +12,7 @@ import {
   QueryKey,
 } from '@tanstack/react-query'
 
-import {useSession} from '#/state/session'
+import {useSession, getAgent} from '#/state/session'
 import {useModerationOpts} from '#/state/queries/preferences'
 import {STALE} from '#/state/queries'
 
@@ -23,7 +23,7 @@ const suggestedFollowsByActorQueryKey = (did: string) => [
 ]
 
 export function useSuggestedFollowsQuery() {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const moderationOpts = useModerationOpts()
 
   return useInfiniteQuery<
@@ -37,7 +37,7 @@ export function useSuggestedFollowsQuery() {
     staleTime: STALE.HOURS.ONE,
     queryKey: suggestedFollowsQueryKey,
     queryFn: async ({pageParam}) => {
-      const res = await agent.app.bsky.actor.getSuggestions({
+      const res = await getAgent().app.bsky.actor.getSuggestions({
         limit: 25,
         cursor: pageParam,
       })
@@ -73,12 +73,10 @@ export function useSuggestedFollowsQuery() {
 }
 
 export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
-  const {agent} = useSession()
-
   return useQuery<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema, Error>({
     queryKey: suggestedFollowsByActorQueryKey(did),
     queryFn: async () => {
-      const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
+      const res = await getAgent().app.bsky.graph.getSuggestedFollowsByActor({
         actor: did,
       })
       return res.data
@@ -87,7 +85,6 @@ export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
 }
 
 export function useGetSuggestedFollowersByActor() {
-  const {agent} = useSession()
   const queryClient = useQueryClient()
 
   return React.useCallback(
@@ -96,15 +93,16 @@ export function useGetSuggestedFollowersByActor() {
         staleTime: 60 * 1000,
         queryKey: suggestedFollowsByActorQueryKey(actor),
         queryFn: async () => {
-          const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
-            actor: actor,
-          })
+          const res =
+            await getAgent().app.bsky.graph.getSuggestedFollowsByActor({
+              actor: actor,
+            })
           return res.data
         },
       })
 
       return res
     },
-    [agent, queryClient],
+    [queryClient],
   )
 }
diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx
index aa45c7bbc..97bd6e976 100644
--- a/src/state/session/index.tsx
+++ b/src/state/session/index.tsx
@@ -1,5 +1,6 @@
 import React from 'react'
 import {BskyAgent, AtpPersistSessionHandler} from '@atproto/api'
+import {useQueryClient} from '@tanstack/react-query'
 
 import {networkRetry} from '#/lib/async/retry'
 import {logger} from '#/logger'
@@ -8,10 +9,15 @@ import {PUBLIC_BSKY_AGENT} from '#/state/queries'
 import {IS_PROD} from '#/lib/constants'
 import {emitSessionLoaded, emitSessionDropped} from '../events'
 
+let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
+
+export function getAgent() {
+  return __globalAgent
+}
+
 export type SessionAccount = persisted.PersistedAccount
 
 export type SessionState = {
-  agent: BskyAgent
   isInitialLoad: boolean
   isSwitchingAccounts: boolean
   accounts: SessionAccount[]
@@ -48,7 +54,6 @@ export type ApiContext = {
 }
 
 const StateContext = React.createContext<StateContext>({
-  agent: PUBLIC_BSKY_AGENT,
   isInitialLoad: true,
   isSwitchingAccounts: false,
   accounts: [],
@@ -110,9 +115,9 @@ function createPersistSessionHandler(
 }
 
 export function Provider({children}: React.PropsWithChildren<{}>) {
+  const queryClient = useQueryClient()
   const isDirty = React.useRef(false)
   const [state, setState] = React.useState<SessionState>({
-    agent: PUBLIC_BSKY_AGENT,
     isInitialLoad: true, // try to resume the session first
     isSwitchingAccounts: false,
     accounts: persisted.get('session').accounts,
@@ -180,7 +185,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
         }),
       )
 
-      setState(s => ({...s, agent}))
+      __globalAgent = agent
+      queryClient.clear()
       upsertAccount(account)
       emitSessionLoaded(account, agent)
 
@@ -193,7 +199,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
         logger.DebugContext.session,
       )
     },
-    [upsertAccount],
+    [upsertAccount, queryClient],
   )
 
   const login = React.useCallback<ApiContext['login']>(
@@ -231,7 +237,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
         }),
       )
 
-      setState(s => ({...s, agent}))
+      __globalAgent = agent
+      queryClient.clear()
       upsertAccount(account)
       emitSessionLoaded(account, agent)
 
@@ -244,7 +251,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
         logger.DebugContext.session,
       )
     },
-    [upsertAccount],
+    [upsertAccount, queryClient],
   )
 
   const logout = React.useCallback<ApiContext['logout']>(async () => {
@@ -308,11 +315,12 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
         accessJwt: agent.session.accessJwt,
       }
 
-      setState(s => ({...s, agent}))
+      __globalAgent = agent
+      queryClient.clear()
       upsertAccount(freshAccount)
       emitSessionLoaded(freshAccount, agent)
     },
-    [upsertAccount],
+    [upsertAccount, queryClient],
   )
 
   const resumeSession = React.useCallback<ApiContext['resumeSession']>(
@@ -399,12 +407,13 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
    * back to the sign-in page.
    */
   const clearCurrentAccount = React.useCallback(() => {
+    __globalAgent = PUBLIC_BSKY_AGENT
+    queryClient.clear()
     setStateAndPersist(s => ({
       ...s,
-      agent: PUBLIC_BSKY_AGENT,
       currentAccount: undefined,
     }))
-  }, [setStateAndPersist])
+  }, [setStateAndPersist, queryClient])
 
   React.useEffect(() => {
     if (isDirty.current) {
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 4db9a3a32..50728cba8 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -56,7 +56,7 @@ import {
   useLanguagePrefsApi,
   toPostLanguages,
 } from '#/state/preferences/languages'
-import {useSession} from '#/state/session'
+import {useSession, getAgent} from '#/state/session'
 import {useProfileQuery} from '#/state/queries/profile'
 import {useComposerControls} from '#/state/shell/composer'
 
@@ -67,7 +67,7 @@ export const ComposePost = observer(function ComposePost({
   quote: initQuote,
   mention: initMention,
 }: Props) {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const {data: currentProfile} = useProfileQuery({did: currentAccount!.did})
   const {activeModals} = useModals()
   const {openModal, closeModal} = useModalControls()
@@ -209,7 +209,7 @@ export const ComposePost = observer(function ComposePost({
     setIsProcessing(true)
 
     try {
-      await apilib.post(agent, {
+      await apilib.post(getAgent(), {
         rawText: richtext.text,
         replyTo: replyTo?.uri,
         images: gallery.images,
diff --git a/src/view/com/composer/useExternalLinkFetch.ts b/src/view/com/composer/useExternalLinkFetch.ts
index af6042306..ef3958c9d 100644
--- a/src/view/com/composer/useExternalLinkFetch.ts
+++ b/src/view/com/composer/useExternalLinkFetch.ts
@@ -16,7 +16,7 @@ import {
 import {ComposerOpts} from 'state/shell/composer'
 import {POST_IMG_MAX} from 'lib/constants'
 import {logger} from '#/logger'
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 import {useGetPost} from '#/state/queries/post'
 
 export function useExternalLinkFetch({
@@ -24,7 +24,6 @@ export function useExternalLinkFetch({
 }: {
   setQuote: (opts: ComposerOpts['quote']) => void
 }) {
-  const {agent} = useSession()
   const [extLink, setExtLink] = useState<apilib.ExternalEmbedDraft | undefined>(
     undefined,
   )
@@ -56,7 +55,7 @@ export function useExternalLinkFetch({
           },
         )
       } else if (isBskyCustomFeedUrl(extLink.uri)) {
-        getFeedAsEmbed(agent, extLink.uri).then(
+        getFeedAsEmbed(getAgent(), extLink.uri).then(
           ({embed, meta}) => {
             if (aborted) {
               return
@@ -74,7 +73,7 @@ export function useExternalLinkFetch({
           },
         )
       } else if (isBskyListUrl(extLink.uri)) {
-        getListAsEmbed(agent, extLink.uri).then(
+        getListAsEmbed(getAgent(), extLink.uri).then(
           ({embed, meta}) => {
             if (aborted) {
               return
@@ -92,7 +91,7 @@ export function useExternalLinkFetch({
           },
         )
       } else {
-        getLinkMeta(agent, extLink.uri).then(meta => {
+        getLinkMeta(getAgent(), extLink.uri).then(meta => {
           if (aborted) {
             return
           }
@@ -134,7 +133,7 @@ export function useExternalLinkFetch({
       })
     }
     return cleanup
-  }, [agent, extLink, setQuote, getPost])
+  }, [extLink, setQuote, getPost])
 
   return {extLink, setExtLink}
 }
diff --git a/src/view/com/modals/ChangeEmail.tsx b/src/view/com/modals/ChangeEmail.tsx
index 829188b51..7ea179688 100644
--- a/src/view/com/modals/ChangeEmail.tsx
+++ b/src/view/com/modals/ChangeEmail.tsx
@@ -13,7 +13,7 @@ import {cleanError} from 'lib/strings/errors'
 import {Trans, msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
-import {useSession, useSessionApi} from '#/state/session'
+import {useSession, useSessionApi, getAgent} from '#/state/session'
 
 enum Stages {
   InputEmail,
@@ -25,7 +25,7 @@ export const snapPoints = ['90%']
 
 export function Component() {
   const pal = usePalette('default')
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const {updateCurrentAccount} = useSessionApi()
   const {_} = useLingui()
   const [stage, setStage] = useState<Stages>(Stages.InputEmail)
@@ -44,11 +44,11 @@ export function Component() {
     setError('')
     setIsProcessing(true)
     try {
-      const res = await agent.com.atproto.server.requestEmailUpdate()
+      const res = await getAgent().com.atproto.server.requestEmailUpdate()
       if (res.data.tokenRequired) {
         setStage(Stages.ConfirmCode)
       } else {
-        await agent.com.atproto.server.updateEmail({email: email.trim()})
+        await getAgent().com.atproto.server.updateEmail({email: email.trim()})
         updateCurrentAccount({
           email: email.trim(),
           emailConfirmed: false,
@@ -77,7 +77,7 @@ export function Component() {
     setError('')
     setIsProcessing(true)
     try {
-      await agent.com.atproto.server.updateEmail({
+      await getAgent().com.atproto.server.updateEmail({
         email: email.trim(),
         token: confirmationCode.trim(),
       })
diff --git a/src/view/com/modals/ChangeHandle.tsx b/src/view/com/modals/ChangeHandle.tsx
index da814b3d4..03516d35a 100644
--- a/src/view/com/modals/ChangeHandle.tsx
+++ b/src/view/com/modals/ChangeHandle.tsx
@@ -26,19 +26,24 @@ import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 import {useServiceQuery} from '#/state/queries/service'
 import {useUpdateHandleMutation, useFetchDid} from '#/state/queries/handle'
-import {useSession, useSessionApi, SessionAccount} from '#/state/session'
+import {
+  useSession,
+  useSessionApi,
+  SessionAccount,
+  getAgent,
+} from '#/state/session'
 
 export const snapPoints = ['100%']
 
 export type Props = {onChanged: () => void}
 
 export function Component(props: Props) {
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const {
     isLoading,
     data: serviceInfo,
     error: serviceInfoError,
-  } = useServiceQuery(agent.service.toString())
+  } = useServiceQuery(getAgent().service.toString())
 
   return isLoading || !currentAccount ? (
     <View style={{padding: 18}}>
diff --git a/src/view/com/modals/DeleteAccount.tsx b/src/view/com/modals/DeleteAccount.tsx
index 7969cf69f..ee16d46b3 100644
--- a/src/view/com/modals/DeleteAccount.tsx
+++ b/src/view/com/modals/DeleteAccount.tsx
@@ -19,14 +19,14 @@ import {resetToTab} from '../../../Navigation'
 import {Trans, msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
-import {useSession, useSessionApi} from '#/state/session'
+import {useSession, useSessionApi, getAgent} from '#/state/session'
 
 export const snapPoints = ['60%']
 
 export function Component({}: {}) {
   const pal = usePalette('default')
   const theme = useTheme()
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const {clearCurrentAccount, removeAccount} = useSessionApi()
   const {_} = useLingui()
   const {closeModal} = useModalControls()
@@ -40,7 +40,7 @@ export function Component({}: {}) {
     setError('')
     setIsProcessing(true)
     try {
-      await agent.com.atproto.server.requestAccountDelete()
+      await getAgent().com.atproto.server.requestAccountDelete()
       setIsEmailSent(true)
     } catch (e: any) {
       setError(cleanError(e))
@@ -57,7 +57,7 @@ export function Component({}: {}) {
     const token = confirmCode.replace(/\s/g, '')
 
     try {
-      await agent.com.atproto.server.deleteAccount({
+      await getAgent().com.atproto.server.deleteAccount({
         did: currentAccount.did,
         password,
         token,
diff --git a/src/view/com/modals/VerifyEmail.tsx b/src/view/com/modals/VerifyEmail.tsx
index e7a4537c5..0af02db4b 100644
--- a/src/view/com/modals/VerifyEmail.tsx
+++ b/src/view/com/modals/VerifyEmail.tsx
@@ -21,7 +21,7 @@ import {cleanError} from 'lib/strings/errors'
 import {Trans, msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
-import {useSession, useSessionApi} from '#/state/session'
+import {useSession, useSessionApi, getAgent} from '#/state/session'
 
 export const snapPoints = ['90%']
 
@@ -33,7 +33,7 @@ enum Stages {
 
 export function Component({showReminder}: {showReminder?: boolean}) {
   const pal = usePalette('default')
-  const {agent, currentAccount} = useSession()
+  const {currentAccount} = useSession()
   const {updateCurrentAccount} = useSessionApi()
   const {_} = useLingui()
   const [stage, setStage] = useState<Stages>(
@@ -49,7 +49,7 @@ export function Component({showReminder}: {showReminder?: boolean}) {
     setError('')
     setIsProcessing(true)
     try {
-      await agent.com.atproto.server.requestEmailConfirmation()
+      await getAgent().com.atproto.server.requestEmailConfirmation()
       setStage(Stages.ConfirmCode)
     } catch (e) {
       setError(cleanError(String(e)))
@@ -62,7 +62,7 @@ export function Component({showReminder}: {showReminder?: boolean}) {
     setError('')
     setIsProcessing(true)
     try {
-      await agent.com.atproto.server.confirmEmail({
+      await getAgent().com.atproto.server.confirmEmail({
         email: (currentAccount?.email || '').trim(),
         token: confirmationCode.trim(),
       })
diff --git a/src/view/com/modals/report/Modal.tsx b/src/view/com/modals/report/Modal.tsx
index 06075547f..60c3f06b7 100644
--- a/src/view/com/modals/report/Modal.tsx
+++ b/src/view/com/modals/report/Modal.tsx
@@ -16,7 +16,7 @@ import {CollectionId} from './types'
 import {Trans, msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
-import {useSession} from '#/state/session'
+import {getAgent} from '#/state/session'
 
 const DMCA_LINK = 'https://blueskyweb.xyz/support/copyright'
 
@@ -39,7 +39,6 @@ type ReportComponentProps =
     }
 
 export function Component(content: ReportComponentProps) {
-  const {agent} = useSession()
   const {closeModal} = useModalControls()
   const pal = usePalette('default')
   const {isMobile} = useWebMediaQueries()
@@ -70,7 +69,7 @@ export function Component(content: ReportComponentProps) {
       const $type = !isAccountReport
         ? 'com.atproto.repo.strongRef'
         : 'com.atproto.admin.defs#repoRef'
-      await agent.createModerationReport({
+      await getAgent().createModerationReport({
         reasonType: issue,
         subject: {
           $type,
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index 916fd2a53..6c61a699b 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -55,7 +55,12 @@ import {
   useRequireAltTextEnabled,
   useSetRequireAltTextEnabled,
 } from '#/state/preferences'
-import {useSession, useSessionApi, SessionAccount} from '#/state/session'
+import {
+  useSession,
+  useSessionApi,
+  SessionAccount,
+  getAgent,
+} from '#/state/session'
 import {useProfileQuery} from '#/state/queries/profile'
 import {useClearPreferencesMutation} from '#/state/queries/preferences'
 import {useInviteCodesQuery} from '#/state/queries/invites'
@@ -148,9 +153,11 @@ export const SettingsScreen = withAuthRequired(function Settings({}: Props) {
   const {isMobile} = useWebMediaQueries()
   const {screen, track} = useAnalytics()
   const {openModal} = useModalControls()
-  const {isSwitchingAccounts, accounts, currentAccount, agent} = useSession()
+  const {isSwitchingAccounts, accounts, currentAccount} = useSession()
   const {clearCurrentAccount} = useSessionApi()
-  const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(agent)
+  const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(
+    getAgent(),
+  )
   const {mutate: clearPreferences} = useClearPreferencesMutation()
   const {data: invites} = useInviteCodesQuery()
   const invitesAvailable = invites?.available?.length ?? 0