---
schema_version: "1"
id: d95e9bae3e696c164b9803b5907a4bcdd43d209d807c63d40f1957a4e966fba6
title: Work with Salesforce Data
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/salesforcedx/agentforcevibes/guides/files/afv-reactdev-data-sdk.md
canonical_url: https://developer.salesforce.com/docs/platform/agentforcevibes/guide/afv-reactdev-data-sdk.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 2d9e9436fd6a4fccbfd4a311330c515294241c27d3d8b6e03a311b303fd89fa0
products:
  - Agentforce Vibes Developer Guide
  - salesforcedx
---
# Work with Salesforce Data

To work with record data in a React app, use the Data SDK to run a GraphQL query or mutation operation.

Agentforce Vibes automatically generates GraphQL data access when your prompt contains one of these intents.

- Fetch data from Salesforce
- Query or update a record
- Add a new GraphQL operation (query or mutation)
- Add data access for a Salesforce object (Account, Contact, Opportunity, etc.)

The base React app provides all GraphQL dependencies and tooling:

- `@salesforce/platform-sdk/data`: Runtime SDK for `createDataSDK` and `gql`
- `@graphql-codegen/cli` and plugins: Type generation from .`graphql` files and inline `gql` queries
- `@graphql-eslint/eslint-plugin`: Linting for .`graphql` files and `gql` template literals
- `graphql`: Shared by codegen, ESLint, and schema introspection

## GraphQL Tooling

If the generated code doesn't use GraphQL and the Data SDK to access data, make sure that:

- The `@salesforce/platform-sdk/data` package is available for the `createDataSDK`, `gql`, and `NodeOfConnection` imports.
- A `schema.graphql` file exists at the project root. If it's missing, generate the file by running `npm run graphql:schema`. This command downloads the full GraphQL schema from a connected Salesforce org via introspection and generates the `schema.graphql` file to the project root.

To generate TypeScript types from .`graphql` files and inline `gql` queries, run this command:

```
npm run graphql:codegen
```

The TypeScript types are generated at `src/api/graphql-operations-types.ts`.

## GraphQL Workflow

Before writing a GraphQL query or mutation operation, Agentforce Vibes explores the schema first before determining the query pattern.

### 1. Explore the schema

The actions for exploring the schema includes:

- Search the `schema.graphql` file for `type <ObjectName> implements Record` to find available fields
- Search for `input <ObjectName>_Filter` for filter options
- Search for `input <ObjectName>_OrderBy` for sorting options

For mutations, Agentforce Vibes searches for input `<ObjectName>CreateInput` or `<ObjectName>UpdateInput`.

### 2. Choose the query pattern

For complex queries, Agentforce Vibes generates an external .`graphql` file. Complex queries are those that include variables, fragments, or those that are shared across files. The external file also enables full codegen type generation.

For simpler queries, an inline `gql` tag is used. Simpler queries don't use variables and are colocated with usage code.

```javascript
import { createDataSDK, gql } from "@salesforce/platform-sdk/data";
import type {
  GetPropertiesQuery,
  GetPropertiesQueryVariables,
} from "../graphql-operations-types";

const GET_PROPERTIES = gql`
  query GetProperties($first: Int) {
    uiapi {
      query {
        Property__c(first: $first) {
          edges {
            node {
              Id
              Name {
                value
              }
              Address__c {
                value
              }
              Status__c {
                value
              }
              Monthly_Rent__c {
                value
              }
              Hero_Image__c {
                value
              }
            }
          }
        }
      }
    }
  }
`;

const dataSdk = await createDataSDK();
const result = await dataSdk.graphql?.query<
  GetPropertiesQuery,
  GetPropertiesQueryVariables
>({
  query: GET_PROPERTIES,
  variables: { first: 50 }
});
```

### 3. Write the query

For complex queries, the .`graphql` file is generated under `src/api/utils/query`. It follows the UI API structure:

```javascript
query GetObjectName {
  uiapi {
    query {
      ObjectName(...) {
        edges {
          node { ... }
        }
      }
    }
  }
}
```

For read queries and mutation queries, Agentforce Vibes dynamically queries the target org, generates the query using the query template, and tests the query.

#### Read Query Generation and Testing

When generating the read query, Agentforce Vibes uses this template.

```javascript
query QueryName {
 uiapi {
   query {
     EntityName(
       # conditions here
     ) {
       edges {
         node {
           # Direct fields
           FieldName { value }
           # Non-polymorphic reference (single type)
           RelationshipName {
             Id
             Name { value }
           }
           # Polymorphic reference (multiple types)
           PolymorphicRelationshipName {
             ...TypeAInfo
             ...TypeBInfo
           }
           # Child relationship (subquery)
           RelationshipName(
             # conditions here
           ) {
             edges {
               node {
                 # fields
               }
             }
           }
         }
       }
     }
   }
 }
}

fragment TypeAInfo on TypeA {
 Id
 SpecificFieldA { value }
}

fragment TypeBInfo on TypeB {
 Id
 SpecificFieldB { value }
}

```

When a read query is successfully generated, the workflow moves into the testing phase. Agentforce Vibes asks you if you want it to test the query using the same method that was used during introspection. If you approve, the query testing starts.

If the query testing fails, Agentforce Vibes identifies the root cause and updates the query accordingly. It resumes testing with the updated query. If the query testing fails after 2 attempts, it asks for additional details and restarts the entire GraphQL workflow from the introspection phase.

#### Mutation Operation Generation and Testing

When generating the mutation operation, Agentforce Vibes uses this template.

```javascript
mutation MutationName($input: EntityNameOperationInput!) {
 uiapi {
   EntityNameOperation(input: $input) {
     # Create/Update operations return Record
     Record {
       # Always include Id
       Id
       # Field values
       FieldName { value }
     }
     # Delete operations return only Id
     Id
   }
 }
}

# Example: Create mutation
mutation CreateAccount($input: AccountCreateInput!) {
 uiapi {
   AccountCreate(input: $input) {
     Record {
       Id
       Name { value }
       Industry { value }
       Phone { value }
     }
   }
 }
}

# Example: Update mutation
mutation UpdateAccount($input: AccountUpdateInput!) {
 uiapi {
   AccountUpdate(input: $input) {
     Record {
       Id
       Name { value }
       AnnualRevenue { value }
     }
   }
 }
}

# Example: Delete mutation
mutation DeleteAccount($input: AccountDeleteInput!) {
 uiapi {
   AccountDelete(input: $input) {
     Id
   }
 }
}
```

When a mutation operation is successfully generated, the workflow moves into the testing phase. Agentforce Vibes asks you if you want it to test the query using the same method that was used during introspection. If you approve, the query testing starts. It then asks you if there are input arguments to use. Agentforce Vibes reports the result of the test based on the `data` and `errors` attributes in the response, as one of these options:

- Partial: Both data and errors aren't empty
- Failed: data is empty
- Success: There are no errors in the response

**note:** When a GraphQL response contains both `data` and `errors` (partial success), the Data SDK preserves the partial data. Partial responses aren't cached; subsequent queries re-fetch data from the network. This allows your app to render fetched data while handling field-level errors.

For partially successful query tests, Agentforce Vibes reports the fields that are mentioned in the `errors` list and explain the cause. For example, the fields can't be queried as part of a mutation operation. It then offers to remove the offending fields. If you agree, Agentforce Vibes restarts the generation workflow with the new field list.

For simpler queries, you get a query inline using the `gql` template tag and a query name that matches what codegen expects. For more information, see the [GraphQL API Dev Guide](https://developer.salesforce.com/docs/platform/graphql/guide/).

### 4. Generate Types

After the query is written, codegen generates or updates the `src/api/graphql-operations-types.ts` file with these types:

- `<OperationName>Query` or `<OperationName>Mutation` — response type
- `<OperationName>QueryVariables` or `<OperationName>MutationVariables` — input variables type

### 5. Implement the Data Access Function

For complex queries with a generated .`graphql` file, the data access function follows this pattern.

```javascript
import { createDataSDK, type NodeOfConnection } from "@salesforce/platform-sdk/data";
import MY_QUERY from "./query/myQuery.graphql?raw";
import type { GetMyDataQuery, GetMyDataQueryVariables } from "../graphql-operations-types";

type MyNode = NodeOfConnection<GetMyDataQuery["uiapi"]["query"]["MyObject"]>;

export async function getMyData(variables: GetMyDataQueryVariables): Promise<MyNode[]> {
 const dataSdk = await createDataSDK();
 const result = await dataSdk.graphql?.query<GetMyDataQuery, GetMyDataQueryVariables>({
   query: MY_QUERY,
   variables,
 });

 if (result?.errors?.length) {
   const errorMessages = result.errors.map((e) => e.message).join("; ");
   throw new Error(`GraphQL Error: ${errorMessages}`);
 }

 return result?.data?.uiapi?.query?.MyObject?.edges?.map((edge) => edge?.node) || [];
}

```

For simpler inline queries, the data access function follows this pattern.

<!-- prettier-ignore -->
```javascript
import { createDataSDK, gql } from "@salesforce/platform-sdk/data";
import type { MySimpleQuery } from "../graphql-operations-types";

const MY_QUERY = gql`
 query MySimple {
   uiapi { ... }
 }
`;

export async function getSimpleData(): Promise<SomeType> {
  const dataSdk = await createDataSDK();
  const result = await dataSdk.graphql?.query<MySimpleQuery>({ query: MY_QUERY });
  // check result.errors, then extract result.data
}
```
